diff options
Diffstat (limited to 'drivers/media/IR')
-rw-r--r-- | drivers/media/IR/Kconfig | 13 | ||||
-rw-r--r-- | drivers/media/IR/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/IR/nuvoton-cir.c | 1216 | ||||
-rw-r--r-- | drivers/media/IR/nuvoton-cir.h | 408 |
4 files changed, 1638 insertions, 0 deletions
diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig index 152000db3526..364514abb6f4 100644 --- a/drivers/media/IR/Kconfig +++ b/drivers/media/IR/Kconfig | |||
@@ -113,6 +113,19 @@ config IR_IMON | |||
113 | To compile this driver as a module, choose M here: the | 113 | To compile this driver as a module, choose M here: the |
114 | module will be called imon. | 114 | module will be called imon. |
115 | 115 | ||
116 | config IR_NUVOTON | ||
117 | tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" | ||
118 | depends on PNP | ||
119 | depends on IR_CORE | ||
120 | ---help--- | ||
121 | Say Y here to enable support for integrated infrared receiver | ||
122 | /transciever made by Nuvoton (formerly Winbond). This chip is | ||
123 | found in the ASRock ION 330HT, as well as assorted Intel | ||
124 | DP55-series motherboards (and of course, possibly others). | ||
125 | |||
126 | To compile this driver as a module, choose M here: the | ||
127 | module will be called nuvoton-cir. | ||
128 | |||
116 | config IR_MCEUSB | 129 | config IR_MCEUSB |
117 | tristate "Windows Media Center Ed. eHome Infrared Transceiver" | 130 | tristate "Windows Media Center Ed. eHome Infrared Transceiver" |
118 | depends on USB_ARCH_HAS_HCD | 131 | depends on USB_ARCH_HAS_HCD |
diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index 953c6c44330a..f9574adab82a 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile | |||
@@ -17,5 +17,6 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o | |||
17 | # stand-alone IR receivers/transmitters | 17 | # stand-alone IR receivers/transmitters |
18 | obj-$(CONFIG_IR_IMON) += imon.o | 18 | obj-$(CONFIG_IR_IMON) += imon.o |
19 | obj-$(CONFIG_IR_MCEUSB) += mceusb.o | 19 | obj-$(CONFIG_IR_MCEUSB) += mceusb.o |
20 | obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o | ||
20 | obj-$(CONFIG_IR_ENE) += ene_ir.o | 21 | obj-$(CONFIG_IR_ENE) += ene_ir.o |
21 | obj-$(CONFIG_IR_STREAMZAP) += streamzap.o | 22 | obj-$(CONFIG_IR_STREAMZAP) += streamzap.o |
diff --git a/drivers/media/IR/nuvoton-cir.c b/drivers/media/IR/nuvoton-cir.c new file mode 100644 index 000000000000..1ce93599ff56 --- /dev/null +++ b/drivers/media/IR/nuvoton-cir.c | |||
@@ -0,0 +1,1216 @@ | |||
1 | /* | ||
2 | * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR | ||
3 | * | ||
4 | * Copyright (C) 2010 Jarod Wilson <jarod@redhat.com> | ||
5 | * Copyright (C) 2009 Nuvoton PS Team | ||
6 | * | ||
7 | * Special thanks to Nuvoton for providing hardware, spec sheets and | ||
8 | * sample code upon which portions of this driver are based. Indirect | ||
9 | * thanks also to Maxim Levitsky, whose ene_ir driver this driver is | ||
10 | * modeled after. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License as | ||
14 | * published by the Free Software Foundation; either version 2 of the | ||
15 | * License, or (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, but | ||
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
20 | * General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
25 | * USA | ||
26 | */ | ||
27 | |||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/pnp.h> | ||
31 | #include <linux/io.h> | ||
32 | #include <linux/interrupt.h> | ||
33 | #include <linux/sched.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/input.h> | ||
36 | #include <media/ir-core.h> | ||
37 | #include <linux/pci_ids.h> | ||
38 | |||
39 | #include "nuvoton-cir.h" | ||
40 | |||
41 | static char *chip_id = "w836x7hg"; | ||
42 | |||
43 | /* write val to config reg */ | ||
44 | static inline void nvt_cr_write(struct nvt_dev *nvt, u8 val, u8 reg) | ||
45 | { | ||
46 | outb(reg, nvt->cr_efir); | ||
47 | outb(val, nvt->cr_efdr); | ||
48 | } | ||
49 | |||
50 | /* read val from config reg */ | ||
51 | static inline u8 nvt_cr_read(struct nvt_dev *nvt, u8 reg) | ||
52 | { | ||
53 | outb(reg, nvt->cr_efir); | ||
54 | return inb(nvt->cr_efdr); | ||
55 | } | ||
56 | |||
57 | /* update config register bit without changing other bits */ | ||
58 | static inline void nvt_set_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg) | ||
59 | { | ||
60 | u8 tmp = nvt_cr_read(nvt, reg) | val; | ||
61 | nvt_cr_write(nvt, tmp, reg); | ||
62 | } | ||
63 | |||
64 | /* clear config register bit without changing other bits */ | ||
65 | static inline void nvt_clear_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg) | ||
66 | { | ||
67 | u8 tmp = nvt_cr_read(nvt, reg) & ~val; | ||
68 | nvt_cr_write(nvt, tmp, reg); | ||
69 | } | ||
70 | |||
71 | /* enter extended function mode */ | ||
72 | static inline void nvt_efm_enable(struct nvt_dev *nvt) | ||
73 | { | ||
74 | /* Enabling Extended Function Mode explicitly requires writing 2x */ | ||
75 | outb(EFER_EFM_ENABLE, nvt->cr_efir); | ||
76 | outb(EFER_EFM_ENABLE, nvt->cr_efir); | ||
77 | } | ||
78 | |||
79 | /* exit extended function mode */ | ||
80 | static inline void nvt_efm_disable(struct nvt_dev *nvt) | ||
81 | { | ||
82 | outb(EFER_EFM_DISABLE, nvt->cr_efir); | ||
83 | } | ||
84 | |||
85 | /* | ||
86 | * When you want to address a specific logical device, write its logical | ||
87 | * device number to CR_LOGICAL_DEV_SEL, then enable/disable by writing | ||
88 | * 0x1/0x0 respectively to CR_LOGICAL_DEV_EN. | ||
89 | */ | ||
90 | static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev) | ||
91 | { | ||
92 | outb(CR_LOGICAL_DEV_SEL, nvt->cr_efir); | ||
93 | outb(ldev, nvt->cr_efdr); | ||
94 | } | ||
95 | |||
96 | /* write val to cir config register */ | ||
97 | static inline void nvt_cir_reg_write(struct nvt_dev *nvt, u8 val, u8 offset) | ||
98 | { | ||
99 | outb(val, nvt->cir_addr + offset); | ||
100 | } | ||
101 | |||
102 | /* read val from cir config register */ | ||
103 | static u8 nvt_cir_reg_read(struct nvt_dev *nvt, u8 offset) | ||
104 | { | ||
105 | u8 val; | ||
106 | |||
107 | val = inb(nvt->cir_addr + offset); | ||
108 | |||
109 | return val; | ||
110 | } | ||
111 | |||
112 | /* write val to cir wake register */ | ||
113 | static inline void nvt_cir_wake_reg_write(struct nvt_dev *nvt, | ||
114 | u8 val, u8 offset) | ||
115 | { | ||
116 | outb(val, nvt->cir_wake_addr + offset); | ||
117 | } | ||
118 | |||
119 | /* read val from cir wake config register */ | ||
120 | static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset) | ||
121 | { | ||
122 | u8 val; | ||
123 | |||
124 | val = inb(nvt->cir_wake_addr + offset); | ||
125 | |||
126 | return val; | ||
127 | } | ||
128 | |||
129 | /* dump current cir register contents */ | ||
130 | static void cir_dump_regs(struct nvt_dev *nvt) | ||
131 | { | ||
132 | nvt_efm_enable(nvt); | ||
133 | nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); | ||
134 | |||
135 | printk("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME); | ||
136 | printk(" * CR CIR ACTIVE : 0x%x\n", | ||
137 | nvt_cr_read(nvt, CR_LOGICAL_DEV_EN)); | ||
138 | printk(" * CR CIR BASE ADDR: 0x%x\n", | ||
139 | (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) | | ||
140 | nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO)); | ||
141 | printk(" * CR CIR IRQ NUM: 0x%x\n", | ||
142 | nvt_cr_read(nvt, CR_CIR_IRQ_RSRC)); | ||
143 | |||
144 | nvt_efm_disable(nvt); | ||
145 | |||
146 | printk("%s: Dump CIR registers:\n", NVT_DRIVER_NAME); | ||
147 | printk(" * IRCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRCON)); | ||
148 | printk(" * IRSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRSTS)); | ||
149 | printk(" * IREN: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IREN)); | ||
150 | printk(" * RXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_RXFCONT)); | ||
151 | printk(" * CP: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CP)); | ||
152 | printk(" * CC: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CC)); | ||
153 | printk(" * SLCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCH)); | ||
154 | printk(" * SLCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCL)); | ||
155 | printk(" * FIFOCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FIFOCON)); | ||
156 | printk(" * IRFIFOSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFIFOSTS)); | ||
157 | printk(" * SRXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SRXFIFO)); | ||
158 | printk(" * TXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_TXFCONT)); | ||
159 | printk(" * STXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_STXFIFO)); | ||
160 | printk(" * FCCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCH)); | ||
161 | printk(" * FCCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCL)); | ||
162 | printk(" * IRFSM: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFSM)); | ||
163 | } | ||
164 | |||
165 | /* dump current cir wake register contents */ | ||
166 | static void cir_wake_dump_regs(struct nvt_dev *nvt) | ||
167 | { | ||
168 | u8 i, fifo_len; | ||
169 | |||
170 | nvt_efm_enable(nvt); | ||
171 | nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); | ||
172 | |||
173 | printk("%s: Dump CIR WAKE logical device registers:\n", | ||
174 | NVT_DRIVER_NAME); | ||
175 | printk(" * CR CIR WAKE ACTIVE : 0x%x\n", | ||
176 | nvt_cr_read(nvt, CR_LOGICAL_DEV_EN)); | ||
177 | printk(" * CR CIR WAKE BASE ADDR: 0x%x\n", | ||
178 | (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) | | ||
179 | nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO)); | ||
180 | printk(" * CR CIR WAKE IRQ NUM: 0x%x\n", | ||
181 | nvt_cr_read(nvt, CR_CIR_IRQ_RSRC)); | ||
182 | |||
183 | nvt_efm_disable(nvt); | ||
184 | |||
185 | printk("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME); | ||
186 | printk(" * IRCON: 0x%x\n", | ||
187 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON)); | ||
188 | printk(" * IRSTS: 0x%x\n", | ||
189 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS)); | ||
190 | printk(" * IREN: 0x%x\n", | ||
191 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN)); | ||
192 | printk(" * FIFO CMP DEEP: 0x%x\n", | ||
193 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP)); | ||
194 | printk(" * FIFO CMP TOL: 0x%x\n", | ||
195 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL)); | ||
196 | printk(" * FIFO COUNT: 0x%x\n", | ||
197 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT)); | ||
198 | printk(" * SLCH: 0x%x\n", | ||
199 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH)); | ||
200 | printk(" * SLCL: 0x%x\n", | ||
201 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL)); | ||
202 | printk(" * FIFOCON: 0x%x\n", | ||
203 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON)); | ||
204 | printk(" * SRXFSTS: 0x%x\n", | ||
205 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS)); | ||
206 | printk(" * SAMPLE RX FIFO: 0x%x\n", | ||
207 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO)); | ||
208 | printk(" * WR FIFO DATA: 0x%x\n", | ||
209 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA)); | ||
210 | printk(" * RD FIFO ONLY: 0x%x\n", | ||
211 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY)); | ||
212 | printk(" * RD FIFO ONLY IDX: 0x%x\n", | ||
213 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)); | ||
214 | printk(" * FIFO IGNORE: 0x%x\n", | ||
215 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE)); | ||
216 | printk(" * IRFSM: 0x%x\n", | ||
217 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM)); | ||
218 | |||
219 | fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT); | ||
220 | printk("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len); | ||
221 | printk("* Contents = "); | ||
222 | for (i = 0; i < fifo_len; i++) | ||
223 | printk("%02x ", | ||
224 | nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY)); | ||
225 | printk("\n"); | ||
226 | } | ||
227 | |||
228 | /* detect hardware features */ | ||
229 | static int nvt_hw_detect(struct nvt_dev *nvt) | ||
230 | { | ||
231 | unsigned long flags; | ||
232 | u8 chip_major, chip_minor; | ||
233 | int ret = 0; | ||
234 | |||
235 | nvt_efm_enable(nvt); | ||
236 | |||
237 | /* Check if we're wired for the alternate EFER setup */ | ||
238 | chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); | ||
239 | if (chip_major == 0xff) { | ||
240 | nvt->cr_efir = CR_EFIR2; | ||
241 | nvt->cr_efdr = CR_EFDR2; | ||
242 | nvt_efm_enable(nvt); | ||
243 | chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); | ||
244 | } | ||
245 | |||
246 | chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); | ||
247 | nvt_dbg("%s: chip id: 0x%02x 0x%02x", chip_id, chip_major, chip_minor); | ||
248 | |||
249 | if (chip_major != CHIP_ID_HIGH && | ||
250 | (chip_minor != CHIP_ID_LOW || chip_minor != CHIP_ID_LOW2)) | ||
251 | ret = -ENODEV; | ||
252 | |||
253 | nvt_efm_disable(nvt); | ||
254 | |||
255 | spin_lock_irqsave(&nvt->nvt_lock, flags); | ||
256 | nvt->chip_major = chip_major; | ||
257 | nvt->chip_minor = chip_minor; | ||
258 | spin_unlock_irqrestore(&nvt->nvt_lock, flags); | ||
259 | |||
260 | return ret; | ||
261 | } | ||
262 | |||
263 | static void nvt_cir_ldev_init(struct nvt_dev *nvt) | ||
264 | { | ||
265 | u8 val; | ||
266 | |||
267 | /* output pin selection (Pin95=CIRRX, Pin96=CIRTX1, WB enabled */ | ||
268 | val = nvt_cr_read(nvt, CR_OUTPUT_PIN_SEL); | ||
269 | val &= OUTPUT_PIN_SEL_MASK; | ||
270 | val |= (OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB); | ||
271 | nvt_cr_write(nvt, val, CR_OUTPUT_PIN_SEL); | ||
272 | |||
273 | /* Select CIR logical device and enable */ | ||
274 | nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); | ||
275 | nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); | ||
276 | |||
277 | nvt_cr_write(nvt, nvt->cir_addr >> 8, CR_CIR_BASE_ADDR_HI); | ||
278 | nvt_cr_write(nvt, nvt->cir_addr & 0xff, CR_CIR_BASE_ADDR_LO); | ||
279 | |||
280 | nvt_cr_write(nvt, nvt->cir_irq, CR_CIR_IRQ_RSRC); | ||
281 | |||
282 | nvt_dbg("CIR initialized, base io port address: 0x%lx, irq: %d", | ||
283 | nvt->cir_addr, nvt->cir_irq); | ||
284 | } | ||
285 | |||
286 | static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt) | ||
287 | { | ||
288 | /* Select ACPI logical device, enable it and CIR Wake */ | ||
289 | nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); | ||
290 | nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); | ||
291 | |||
292 | /* Enable CIR Wake via PSOUT# (Pin60) */ | ||
293 | nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE); | ||
294 | |||
295 | /* enable cir interrupt of mouse/keyboard IRQ event */ | ||
296 | nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS); | ||
297 | |||
298 | /* enable pme interrupt of cir wakeup event */ | ||
299 | nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2); | ||
300 | |||
301 | /* Select CIR Wake logical device and enable */ | ||
302 | nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); | ||
303 | nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); | ||
304 | |||
305 | nvt_cr_write(nvt, nvt->cir_wake_addr >> 8, CR_CIR_BASE_ADDR_HI); | ||
306 | nvt_cr_write(nvt, nvt->cir_wake_addr & 0xff, CR_CIR_BASE_ADDR_LO); | ||
307 | |||
308 | nvt_cr_write(nvt, nvt->cir_wake_irq, CR_CIR_IRQ_RSRC); | ||
309 | |||
310 | nvt_dbg("CIR Wake initialized, base io port address: 0x%lx, irq: %d", | ||
311 | nvt->cir_wake_addr, nvt->cir_wake_irq); | ||
312 | } | ||
313 | |||
314 | /* clear out the hardware's cir rx fifo */ | ||
315 | static void nvt_clear_cir_fifo(struct nvt_dev *nvt) | ||
316 | { | ||
317 | u8 val; | ||
318 | |||
319 | val = nvt_cir_reg_read(nvt, CIR_FIFOCON); | ||
320 | nvt_cir_reg_write(nvt, val | CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON); | ||
321 | } | ||
322 | |||
323 | /* clear out the hardware's cir wake rx fifo */ | ||
324 | static void nvt_clear_cir_wake_fifo(struct nvt_dev *nvt) | ||
325 | { | ||
326 | u8 val; | ||
327 | |||
328 | val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON); | ||
329 | nvt_cir_wake_reg_write(nvt, val | CIR_WAKE_FIFOCON_RXFIFOCLR, | ||
330 | CIR_WAKE_FIFOCON); | ||
331 | } | ||
332 | |||
333 | /* clear out the hardware's cir tx fifo */ | ||
334 | static void nvt_clear_tx_fifo(struct nvt_dev *nvt) | ||
335 | { | ||
336 | u8 val; | ||
337 | |||
338 | val = nvt_cir_reg_read(nvt, CIR_FIFOCON); | ||
339 | nvt_cir_reg_write(nvt, val | CIR_FIFOCON_TXFIFOCLR, CIR_FIFOCON); | ||
340 | } | ||
341 | |||
342 | static void nvt_cir_regs_init(struct nvt_dev *nvt) | ||
343 | { | ||
344 | /* set sample limit count (PE interrupt raised when reached) */ | ||
345 | nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_SLCH); | ||
346 | nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_SLCL); | ||
347 | |||
348 | /* set fifo irq trigger levels */ | ||
349 | nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV | | ||
350 | CIR_FIFOCON_RX_TRIGGER_LEV, CIR_FIFOCON); | ||
351 | |||
352 | /* | ||
353 | * Enable TX and RX, specify carrier on = low, off = high, and set | ||
354 | * sample period (currently 50us) | ||
355 | */ | ||
356 | nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | CIR_IRCON_RXINV | | ||
357 | CIR_IRCON_SAMPLE_PERIOD_SEL, CIR_IRCON); | ||
358 | |||
359 | /* clear hardware rx and tx fifos */ | ||
360 | nvt_clear_cir_fifo(nvt); | ||
361 | nvt_clear_tx_fifo(nvt); | ||
362 | |||
363 | /* clear any and all stray interrupts */ | ||
364 | nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); | ||
365 | |||
366 | /* and finally, enable RX Trigger Level Read and Packet End interrupts */ | ||
367 | nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); | ||
368 | } | ||
369 | |||
370 | static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) | ||
371 | { | ||
372 | /* set number of bytes needed for wake key comparison (default 67) */ | ||
373 | nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFO_LEN, CIR_WAKE_FIFO_CMP_DEEP); | ||
374 | |||
375 | /* set tolerance/variance allowed per byte during wake compare */ | ||
376 | nvt_cir_wake_reg_write(nvt, CIR_WAKE_CMP_TOLERANCE, | ||
377 | CIR_WAKE_FIFO_CMP_TOL); | ||
378 | |||
379 | /* set sample limit count (PE interrupt raised when reached) */ | ||
380 | nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_WAKE_SLCH); | ||
381 | nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_WAKE_SLCL); | ||
382 | |||
383 | /* set cir wake fifo rx trigger level (currently 67) */ | ||
384 | nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFOCON_RX_TRIGGER_LEV, | ||
385 | CIR_WAKE_FIFOCON); | ||
386 | |||
387 | /* | ||
388 | * Enable TX and RX, specific carrier on = low, off = high, and set | ||
389 | * sample period (currently 50us) | ||
390 | */ | ||
391 | nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | | ||
392 | CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | | ||
393 | CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, | ||
394 | CIR_WAKE_IRCON); | ||
395 | |||
396 | /* clear cir wake rx fifo */ | ||
397 | nvt_clear_cir_wake_fifo(nvt); | ||
398 | |||
399 | /* clear any and all stray interrupts */ | ||
400 | nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); | ||
401 | } | ||
402 | |||
403 | static void nvt_enable_wake(struct nvt_dev *nvt) | ||
404 | { | ||
405 | nvt_efm_enable(nvt); | ||
406 | |||
407 | nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); | ||
408 | nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE); | ||
409 | nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS); | ||
410 | nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2); | ||
411 | |||
412 | nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); | ||
413 | nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); | ||
414 | |||
415 | nvt_efm_disable(nvt); | ||
416 | |||
417 | nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | | ||
418 | CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | | ||
419 | CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, CIR_WAKE_IRCON); | ||
420 | nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); | ||
421 | nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); | ||
422 | } | ||
423 | |||
424 | /* rx carrier detect only works in learning mode, must be called w/nvt_lock */ | ||
425 | static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt) | ||
426 | { | ||
427 | u32 count, carrier, duration = 0; | ||
428 | int i; | ||
429 | |||
430 | count = nvt_cir_reg_read(nvt, CIR_FCCL) | | ||
431 | nvt_cir_reg_read(nvt, CIR_FCCH) << 8; | ||
432 | |||
433 | for (i = 0; i < nvt->pkts; i++) { | ||
434 | if (nvt->buf[i] & BUF_PULSE_BIT) | ||
435 | duration += nvt->buf[i] & BUF_LEN_MASK; | ||
436 | } | ||
437 | |||
438 | duration *= SAMPLE_PERIOD; | ||
439 | |||
440 | if (!count || !duration) { | ||
441 | nvt_pr(KERN_NOTICE, "Unable to determine carrier! (c:%u, d:%u)", | ||
442 | count, duration); | ||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | carrier = (count * 1000000) / duration; | ||
447 | |||
448 | if ((carrier > MAX_CARRIER) || (carrier < MIN_CARRIER)) | ||
449 | nvt_dbg("WTF? Carrier frequency out of range!"); | ||
450 | |||
451 | nvt_dbg("Carrier frequency: %u (count %u, duration %u)", | ||
452 | carrier, count, duration); | ||
453 | |||
454 | return carrier; | ||
455 | } | ||
456 | |||
457 | /* | ||
458 | * set carrier frequency | ||
459 | * | ||
460 | * set carrier on 2 registers: CP & CC | ||
461 | * always set CP as 0x81 | ||
462 | * set CC by SPEC, CC = 3MHz/carrier - 1 | ||
463 | */ | ||
464 | static int nvt_set_tx_carrier(void *data, u32 carrier) | ||
465 | { | ||
466 | struct nvt_dev *nvt = data; | ||
467 | u16 val; | ||
468 | |||
469 | nvt_cir_reg_write(nvt, 1, CIR_CP); | ||
470 | val = 3000000 / (carrier) - 1; | ||
471 | nvt_cir_reg_write(nvt, val & 0xff, CIR_CC); | ||
472 | |||
473 | nvt_dbg("cp: 0x%x cc: 0x%x\n", | ||
474 | nvt_cir_reg_read(nvt, CIR_CP), nvt_cir_reg_read(nvt, CIR_CC)); | ||
475 | |||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | /* | ||
480 | * nvt_tx_ir | ||
481 | * | ||
482 | * 1) clean TX fifo first (handled by AP) | ||
483 | * 2) copy data from user space | ||
484 | * 3) disable RX interrupts, enable TX interrupts: TTR & TFU | ||
485 | * 4) send 9 packets to TX FIFO to open TTR | ||
486 | * in interrupt_handler: | ||
487 | * 5) send all data out | ||
488 | * go back to write(): | ||
489 | * 6) disable TX interrupts, re-enable RX interupts | ||
490 | * | ||
491 | * The key problem of this function is user space data may larger than | ||
492 | * driver's data buf length. So nvt_tx_ir() will only copy TX_BUF_LEN data to | ||
493 | * buf, and keep current copied data buf num in cur_buf_num. But driver's buf | ||
494 | * number may larger than TXFCONT (0xff). So in interrupt_handler, it has to | ||
495 | * set TXFCONT as 0xff, until buf_count less than 0xff. | ||
496 | */ | ||
497 | static int nvt_tx_ir(void *priv, int *txbuf, u32 n) | ||
498 | { | ||
499 | struct nvt_dev *nvt = priv; | ||
500 | unsigned long flags; | ||
501 | size_t cur_count; | ||
502 | unsigned int i; | ||
503 | u8 iren; | ||
504 | int ret; | ||
505 | |||
506 | spin_lock_irqsave(&nvt->tx.lock, flags); | ||
507 | |||
508 | if (n >= TX_BUF_LEN) { | ||
509 | nvt->tx.buf_count = cur_count = TX_BUF_LEN; | ||
510 | ret = TX_BUF_LEN; | ||
511 | } else { | ||
512 | nvt->tx.buf_count = cur_count = n; | ||
513 | ret = n; | ||
514 | } | ||
515 | |||
516 | memcpy(nvt->tx.buf, txbuf, nvt->tx.buf_count); | ||
517 | |||
518 | nvt->tx.cur_buf_num = 0; | ||
519 | |||
520 | /* save currently enabled interrupts */ | ||
521 | iren = nvt_cir_reg_read(nvt, CIR_IREN); | ||
522 | |||
523 | /* now disable all interrupts, save TFU & TTR */ | ||
524 | nvt_cir_reg_write(nvt, CIR_IREN_TFU | CIR_IREN_TTR, CIR_IREN); | ||
525 | |||
526 | nvt->tx.tx_state = ST_TX_REPLY; | ||
527 | |||
528 | nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV_8 | | ||
529 | CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON); | ||
530 | |||
531 | /* trigger TTR interrupt by writing out ones, (yes, it's ugly) */ | ||
532 | for (i = 0; i < 9; i++) | ||
533 | nvt_cir_reg_write(nvt, 0x01, CIR_STXFIFO); | ||
534 | |||
535 | spin_unlock_irqrestore(&nvt->tx.lock, flags); | ||
536 | |||
537 | wait_event(nvt->tx.queue, nvt->tx.tx_state == ST_TX_REQUEST); | ||
538 | |||
539 | spin_lock_irqsave(&nvt->tx.lock, flags); | ||
540 | nvt->tx.tx_state = ST_TX_NONE; | ||
541 | spin_unlock_irqrestore(&nvt->tx.lock, flags); | ||
542 | |||
543 | /* restore enabled interrupts to prior state */ | ||
544 | nvt_cir_reg_write(nvt, iren, CIR_IREN); | ||
545 | |||
546 | return ret; | ||
547 | } | ||
548 | |||
549 | /* dump contents of the last rx buffer we got from the hw rx fifo */ | ||
550 | static void nvt_dump_rx_buf(struct nvt_dev *nvt) | ||
551 | { | ||
552 | int i; | ||
553 | |||
554 | printk("%s (len %d): ", __func__, nvt->pkts); | ||
555 | for (i = 0; (i < nvt->pkts) && (i < RX_BUF_LEN); i++) | ||
556 | printk("0x%02x ", nvt->buf[i]); | ||
557 | printk("\n"); | ||
558 | } | ||
559 | |||
560 | /* | ||
561 | * Process raw data in rx driver buffer, store it in raw IR event kfifo, | ||
562 | * trigger decode when appropriate. | ||
563 | * | ||
564 | * We get IR data samples one byte at a time. If the msb is set, its a pulse, | ||
565 | * otherwise its a space. The lower 7 bits are the count of SAMPLE_PERIOD | ||
566 | * (default 50us) intervals for that pulse/space. A discrete signal is | ||
567 | * followed by a series of 0x7f packets, then either 0x7<something> or 0x80 | ||
568 | * to signal more IR coming (repeats) or end of IR, respectively. We store | ||
569 | * sample data in the raw event kfifo until we see 0x7<something> (except f) | ||
570 | * or 0x80, at which time, we trigger a decode operation. | ||
571 | */ | ||
572 | static void nvt_process_rx_ir_data(struct nvt_dev *nvt) | ||
573 | { | ||
574 | struct ir_raw_event rawir = { .pulse = false, .duration = 0 }; | ||
575 | unsigned int count; | ||
576 | u32 carrier; | ||
577 | u8 sample; | ||
578 | int i; | ||
579 | |||
580 | nvt_dbg_verbose("%s firing", __func__); | ||
581 | |||
582 | if (debug) | ||
583 | nvt_dump_rx_buf(nvt); | ||
584 | |||
585 | if (nvt->carrier_detect_enabled) | ||
586 | carrier = nvt_rx_carrier_detect(nvt); | ||
587 | |||
588 | count = nvt->pkts; | ||
589 | nvt_dbg_verbose("Processing buffer of len %d", count); | ||
590 | |||
591 | for (i = 0; i < count; i++) { | ||
592 | nvt->pkts--; | ||
593 | sample = nvt->buf[i]; | ||
594 | |||
595 | rawir.pulse = ((sample & BUF_PULSE_BIT) != 0); | ||
596 | rawir.duration = (sample & BUF_LEN_MASK) | ||
597 | * SAMPLE_PERIOD * 1000; | ||
598 | |||
599 | if ((sample & BUF_LEN_MASK) == BUF_LEN_MASK) { | ||
600 | if (nvt->rawir.pulse == rawir.pulse) | ||
601 | nvt->rawir.duration += rawir.duration; | ||
602 | else { | ||
603 | nvt->rawir.duration = rawir.duration; | ||
604 | nvt->rawir.pulse = rawir.pulse; | ||
605 | } | ||
606 | continue; | ||
607 | } | ||
608 | |||
609 | rawir.duration += nvt->rawir.duration; | ||
610 | nvt->rawir.duration = 0; | ||
611 | nvt->rawir.pulse = rawir.pulse; | ||
612 | |||
613 | if (sample == BUF_PULSE_BIT) | ||
614 | rawir.pulse = false; | ||
615 | |||
616 | if (rawir.duration) { | ||
617 | nvt_dbg("Storing %s with duration %d", | ||
618 | rawir.pulse ? "pulse" : "space", | ||
619 | rawir.duration); | ||
620 | |||
621 | ir_raw_event_store(nvt->rdev, &rawir); | ||
622 | } | ||
623 | |||
624 | /* | ||
625 | * BUF_PULSE_BIT indicates end of IR data, BUF_REPEAT_BYTE | ||
626 | * indicates end of IR signal, but new data incoming. In both | ||
627 | * cases, it means we're ready to call ir_raw_event_handle | ||
628 | */ | ||
629 | if (sample == BUF_PULSE_BIT || ((sample != BUF_LEN_MASK) && | ||
630 | (sample & BUF_REPEAT_MASK) == BUF_REPEAT_BYTE)) | ||
631 | ir_raw_event_handle(nvt->rdev); | ||
632 | } | ||
633 | |||
634 | if (nvt->pkts) { | ||
635 | nvt_dbg("Odd, pkts should be 0 now... (its %u)", nvt->pkts); | ||
636 | nvt->pkts = 0; | ||
637 | } | ||
638 | |||
639 | nvt_dbg_verbose("%s done", __func__); | ||
640 | } | ||
641 | |||
642 | /* copy data from hardware rx fifo into driver buffer */ | ||
643 | static void nvt_get_rx_ir_data(struct nvt_dev *nvt) | ||
644 | { | ||
645 | unsigned long flags; | ||
646 | u8 fifocount, val; | ||
647 | unsigned int b_idx; | ||
648 | int i; | ||
649 | |||
650 | /* Get count of how many bytes to read from RX FIFO */ | ||
651 | fifocount = nvt_cir_reg_read(nvt, CIR_RXFCONT); | ||
652 | /* if we get 0xff, probably means the logical dev is disabled */ | ||
653 | if (fifocount == 0xff) | ||
654 | return; | ||
655 | /* this would suggest a fifo overrun, not good... */ | ||
656 | else if (fifocount > RX_BUF_LEN) { | ||
657 | nvt_pr(KERN_WARNING, "fifocount %d over fifo len (%d)!", | ||
658 | fifocount, RX_BUF_LEN); | ||
659 | return; | ||
660 | } | ||
661 | |||
662 | nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount); | ||
663 | |||
664 | spin_lock_irqsave(&nvt->nvt_lock, flags); | ||
665 | |||
666 | b_idx = nvt->pkts; | ||
667 | |||
668 | /* This should never happen, but lets check anyway... */ | ||
669 | if (b_idx + fifocount > RX_BUF_LEN) { | ||
670 | nvt_process_rx_ir_data(nvt); | ||
671 | b_idx = 0; | ||
672 | } | ||
673 | |||
674 | /* Read fifocount bytes from CIR Sample RX FIFO register */ | ||
675 | for (i = 0; i < fifocount; i++) { | ||
676 | val = nvt_cir_reg_read(nvt, CIR_SRXFIFO); | ||
677 | nvt->buf[b_idx + i] = val; | ||
678 | } | ||
679 | |||
680 | nvt->pkts += fifocount; | ||
681 | nvt_dbg("%s: pkts now %d", __func__, nvt->pkts); | ||
682 | |||
683 | nvt_process_rx_ir_data(nvt); | ||
684 | |||
685 | spin_unlock_irqrestore(&nvt->nvt_lock, flags); | ||
686 | } | ||
687 | |||
688 | static void nvt_cir_log_irqs(u8 status, u8 iren) | ||
689 | { | ||
690 | nvt_pr(KERN_INFO, "IRQ 0x%02x (IREN 0x%02x) :%s%s%s%s%s%s%s%s%s", | ||
691 | status, iren, | ||
692 | status & CIR_IRSTS_RDR ? " RDR" : "", | ||
693 | status & CIR_IRSTS_RTR ? " RTR" : "", | ||
694 | status & CIR_IRSTS_PE ? " PE" : "", | ||
695 | status & CIR_IRSTS_RFO ? " RFO" : "", | ||
696 | status & CIR_IRSTS_TE ? " TE" : "", | ||
697 | status & CIR_IRSTS_TTR ? " TTR" : "", | ||
698 | status & CIR_IRSTS_TFU ? " TFU" : "", | ||
699 | status & CIR_IRSTS_GH ? " GH" : "", | ||
700 | status & ~(CIR_IRSTS_RDR | CIR_IRSTS_RTR | CIR_IRSTS_PE | | ||
701 | CIR_IRSTS_RFO | CIR_IRSTS_TE | CIR_IRSTS_TTR | | ||
702 | CIR_IRSTS_TFU | CIR_IRSTS_GH) ? " ?" : ""); | ||
703 | } | ||
704 | |||
705 | static bool nvt_cir_tx_inactive(struct nvt_dev *nvt) | ||
706 | { | ||
707 | unsigned long flags; | ||
708 | bool tx_inactive; | ||
709 | u8 tx_state; | ||
710 | |||
711 | spin_lock_irqsave(&nvt->tx.lock, flags); | ||
712 | tx_state = nvt->tx.tx_state; | ||
713 | spin_unlock_irqrestore(&nvt->tx.lock, flags); | ||
714 | |||
715 | tx_inactive = (tx_state == ST_TX_NONE); | ||
716 | |||
717 | return tx_inactive; | ||
718 | } | ||
719 | |||
720 | /* interrupt service routine for incoming and outgoing CIR data */ | ||
721 | static irqreturn_t nvt_cir_isr(int irq, void *data) | ||
722 | { | ||
723 | struct nvt_dev *nvt = data; | ||
724 | u8 status, iren, cur_state; | ||
725 | unsigned long flags; | ||
726 | |||
727 | nvt_dbg_verbose("%s firing", __func__); | ||
728 | |||
729 | nvt_efm_enable(nvt); | ||
730 | nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); | ||
731 | nvt_efm_disable(nvt); | ||
732 | |||
733 | /* | ||
734 | * Get IR Status register contents. Write 1 to ack/clear | ||
735 | * | ||
736 | * bit: reg name - description | ||
737 | * 7: CIR_IRSTS_RDR - RX Data Ready | ||
738 | * 6: CIR_IRSTS_RTR - RX FIFO Trigger Level Reach | ||
739 | * 5: CIR_IRSTS_PE - Packet End | ||
740 | * 4: CIR_IRSTS_RFO - RX FIFO Overrun (RDR will also be set) | ||
741 | * 3: CIR_IRSTS_TE - TX FIFO Empty | ||
742 | * 2: CIR_IRSTS_TTR - TX FIFO Trigger Level Reach | ||
743 | * 1: CIR_IRSTS_TFU - TX FIFO Underrun | ||
744 | * 0: CIR_IRSTS_GH - Min Length Detected | ||
745 | */ | ||
746 | status = nvt_cir_reg_read(nvt, CIR_IRSTS); | ||
747 | if (!status) { | ||
748 | nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__); | ||
749 | nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); | ||
750 | return IRQ_RETVAL(IRQ_NONE); | ||
751 | } | ||
752 | |||
753 | /* ack/clear all irq flags we've got */ | ||
754 | nvt_cir_reg_write(nvt, status, CIR_IRSTS); | ||
755 | nvt_cir_reg_write(nvt, 0, CIR_IRSTS); | ||
756 | |||
757 | /* Interrupt may be shared with CIR Wake, bail if CIR not enabled */ | ||
758 | iren = nvt_cir_reg_read(nvt, CIR_IREN); | ||
759 | if (!iren) { | ||
760 | nvt_dbg_verbose("%s exiting, CIR not enabled", __func__); | ||
761 | return IRQ_RETVAL(IRQ_NONE); | ||
762 | } | ||
763 | |||
764 | if (debug) | ||
765 | nvt_cir_log_irqs(status, iren); | ||
766 | |||
767 | if (status & CIR_IRSTS_RTR) { | ||
768 | /* FIXME: add code for study/learn mode */ | ||
769 | /* We only do rx if not tx'ing */ | ||
770 | if (nvt_cir_tx_inactive(nvt)) | ||
771 | nvt_get_rx_ir_data(nvt); | ||
772 | } | ||
773 | |||
774 | if (status & CIR_IRSTS_PE) { | ||
775 | if (nvt_cir_tx_inactive(nvt)) | ||
776 | nvt_get_rx_ir_data(nvt); | ||
777 | |||
778 | spin_lock_irqsave(&nvt->nvt_lock, flags); | ||
779 | |||
780 | cur_state = nvt->study_state; | ||
781 | |||
782 | spin_unlock_irqrestore(&nvt->nvt_lock, flags); | ||
783 | |||
784 | if (cur_state == ST_STUDY_NONE) | ||
785 | nvt_clear_cir_fifo(nvt); | ||
786 | } | ||
787 | |||
788 | if (status & CIR_IRSTS_TE) | ||
789 | nvt_clear_tx_fifo(nvt); | ||
790 | |||
791 | if (status & CIR_IRSTS_TTR) { | ||
792 | unsigned int pos, count; | ||
793 | u8 tmp; | ||
794 | |||
795 | spin_lock_irqsave(&nvt->tx.lock, flags); | ||
796 | |||
797 | pos = nvt->tx.cur_buf_num; | ||
798 | count = nvt->tx.buf_count; | ||
799 | |||
800 | /* Write data into the hardware tx fifo while pos < count */ | ||
801 | if (pos < count) { | ||
802 | nvt_cir_reg_write(nvt, nvt->tx.buf[pos], CIR_STXFIFO); | ||
803 | nvt->tx.cur_buf_num++; | ||
804 | /* Disable TX FIFO Trigger Level Reach (TTR) interrupt */ | ||
805 | } else { | ||
806 | tmp = nvt_cir_reg_read(nvt, CIR_IREN); | ||
807 | nvt_cir_reg_write(nvt, tmp & ~CIR_IREN_TTR, CIR_IREN); | ||
808 | } | ||
809 | |||
810 | spin_unlock_irqrestore(&nvt->tx.lock, flags); | ||
811 | |||
812 | } | ||
813 | |||
814 | if (status & CIR_IRSTS_TFU) { | ||
815 | spin_lock_irqsave(&nvt->tx.lock, flags); | ||
816 | if (nvt->tx.tx_state == ST_TX_REPLY) { | ||
817 | nvt->tx.tx_state = ST_TX_REQUEST; | ||
818 | wake_up(&nvt->tx.queue); | ||
819 | } | ||
820 | spin_unlock_irqrestore(&nvt->tx.lock, flags); | ||
821 | } | ||
822 | |||
823 | nvt_dbg_verbose("%s done", __func__); | ||
824 | return IRQ_RETVAL(IRQ_HANDLED); | ||
825 | } | ||
826 | |||
827 | /* Interrupt service routine for CIR Wake */ | ||
828 | static irqreturn_t nvt_cir_wake_isr(int irq, void *data) | ||
829 | { | ||
830 | u8 status, iren, val; | ||
831 | struct nvt_dev *nvt = data; | ||
832 | unsigned long flags; | ||
833 | |||
834 | nvt_dbg_wake("%s firing", __func__); | ||
835 | |||
836 | status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS); | ||
837 | if (!status) | ||
838 | return IRQ_RETVAL(IRQ_NONE); | ||
839 | |||
840 | if (status & CIR_WAKE_IRSTS_IR_PENDING) | ||
841 | nvt_clear_cir_wake_fifo(nvt); | ||
842 | |||
843 | nvt_cir_wake_reg_write(nvt, status, CIR_WAKE_IRSTS); | ||
844 | nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IRSTS); | ||
845 | |||
846 | /* Interrupt may be shared with CIR, bail if Wake not enabled */ | ||
847 | iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); | ||
848 | if (!iren) { | ||
849 | nvt_dbg_wake("%s exiting, wake not enabled", __func__); | ||
850 | return IRQ_RETVAL(IRQ_HANDLED); | ||
851 | } | ||
852 | |||
853 | if ((status & CIR_WAKE_IRSTS_PE) && | ||
854 | (nvt->wake_state == ST_WAKE_START)) { | ||
855 | while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)) { | ||
856 | val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY); | ||
857 | nvt_dbg("setting wake up key: 0x%x", val); | ||
858 | } | ||
859 | |||
860 | nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); | ||
861 | spin_lock_irqsave(&nvt->nvt_lock, flags); | ||
862 | nvt->wake_state = ST_WAKE_FINISH; | ||
863 | spin_unlock_irqrestore(&nvt->nvt_lock, flags); | ||
864 | } | ||
865 | |||
866 | nvt_dbg_wake("%s done", __func__); | ||
867 | return IRQ_RETVAL(IRQ_HANDLED); | ||
868 | } | ||
869 | |||
870 | static void nvt_enable_cir(struct nvt_dev *nvt) | ||
871 | { | ||
872 | /* set function enable flags */ | ||
873 | nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | | ||
874 | CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, | ||
875 | CIR_IRCON); | ||
876 | |||
877 | nvt_efm_enable(nvt); | ||
878 | |||
879 | /* enable the CIR logical device */ | ||
880 | nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); | ||
881 | nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); | ||
882 | |||
883 | nvt_efm_disable(nvt); | ||
884 | |||
885 | /* clear all pending interrupts */ | ||
886 | nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); | ||
887 | |||
888 | /* enable interrupts */ | ||
889 | nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); | ||
890 | } | ||
891 | |||
892 | static void nvt_disable_cir(struct nvt_dev *nvt) | ||
893 | { | ||
894 | /* disable CIR interrupts */ | ||
895 | nvt_cir_reg_write(nvt, 0, CIR_IREN); | ||
896 | |||
897 | /* clear any and all pending interrupts */ | ||
898 | nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); | ||
899 | |||
900 | /* clear all function enable flags */ | ||
901 | nvt_cir_reg_write(nvt, 0, CIR_IRCON); | ||
902 | |||
903 | /* clear hardware rx and tx fifos */ | ||
904 | nvt_clear_cir_fifo(nvt); | ||
905 | nvt_clear_tx_fifo(nvt); | ||
906 | |||
907 | nvt_efm_enable(nvt); | ||
908 | |||
909 | /* disable the CIR logical device */ | ||
910 | nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); | ||
911 | nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); | ||
912 | |||
913 | nvt_efm_disable(nvt); | ||
914 | } | ||
915 | |||
916 | static int nvt_open(void *data) | ||
917 | { | ||
918 | struct nvt_dev *nvt = (struct nvt_dev *)data; | ||
919 | unsigned long flags; | ||
920 | |||
921 | spin_lock_irqsave(&nvt->nvt_lock, flags); | ||
922 | nvt->in_use = true; | ||
923 | nvt_enable_cir(nvt); | ||
924 | spin_unlock_irqrestore(&nvt->nvt_lock, flags); | ||
925 | |||
926 | return 0; | ||
927 | } | ||
928 | |||
929 | static void nvt_close(void *data) | ||
930 | { | ||
931 | struct nvt_dev *nvt = (struct nvt_dev *)data; | ||
932 | unsigned long flags; | ||
933 | |||
934 | spin_lock_irqsave(&nvt->nvt_lock, flags); | ||
935 | nvt->in_use = false; | ||
936 | nvt_disable_cir(nvt); | ||
937 | spin_unlock_irqrestore(&nvt->nvt_lock, flags); | ||
938 | } | ||
939 | |||
940 | /* Allocate memory, probe hardware, and initialize everything */ | ||
941 | static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) | ||
942 | { | ||
943 | struct nvt_dev *nvt = NULL; | ||
944 | struct input_dev *rdev = NULL; | ||
945 | struct ir_dev_props *props = NULL; | ||
946 | int ret = -ENOMEM; | ||
947 | |||
948 | nvt = kzalloc(sizeof(struct nvt_dev), GFP_KERNEL); | ||
949 | if (!nvt) | ||
950 | return ret; | ||
951 | |||
952 | props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); | ||
953 | if (!props) | ||
954 | goto failure; | ||
955 | |||
956 | /* input device for IR remote (and tx) */ | ||
957 | rdev = input_allocate_device(); | ||
958 | if (!rdev) | ||
959 | goto failure; | ||
960 | |||
961 | ret = -ENODEV; | ||
962 | /* validate pnp resources */ | ||
963 | if (!pnp_port_valid(pdev, 0) || | ||
964 | pnp_port_len(pdev, 0) < CIR_IOREG_LENGTH) { | ||
965 | dev_err(&pdev->dev, "IR PNP Port not valid!\n"); | ||
966 | goto failure; | ||
967 | } | ||
968 | |||
969 | if (!pnp_irq_valid(pdev, 0)) { | ||
970 | dev_err(&pdev->dev, "PNP IRQ not valid!\n"); | ||
971 | goto failure; | ||
972 | } | ||
973 | |||
974 | if (!pnp_port_valid(pdev, 1) || | ||
975 | pnp_port_len(pdev, 1) < CIR_IOREG_LENGTH) { | ||
976 | dev_err(&pdev->dev, "Wake PNP Port not valid!\n"); | ||
977 | goto failure; | ||
978 | } | ||
979 | |||
980 | nvt->cir_addr = pnp_port_start(pdev, 0); | ||
981 | nvt->cir_irq = pnp_irq(pdev, 0); | ||
982 | |||
983 | nvt->cir_wake_addr = pnp_port_start(pdev, 1); | ||
984 | /* irq is always shared between cir and cir wake */ | ||
985 | nvt->cir_wake_irq = nvt->cir_irq; | ||
986 | |||
987 | nvt->cr_efir = CR_EFIR; | ||
988 | nvt->cr_efdr = CR_EFDR; | ||
989 | |||
990 | spin_lock_init(&nvt->nvt_lock); | ||
991 | spin_lock_init(&nvt->tx.lock); | ||
992 | |||
993 | ret = -EBUSY; | ||
994 | /* now claim resources */ | ||
995 | if (!request_region(nvt->cir_addr, | ||
996 | CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) | ||
997 | goto failure; | ||
998 | |||
999 | if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED, | ||
1000 | NVT_DRIVER_NAME, (void *)nvt)) | ||
1001 | goto failure; | ||
1002 | |||
1003 | if (!request_region(nvt->cir_wake_addr, | ||
1004 | CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) | ||
1005 | goto failure; | ||
1006 | |||
1007 | if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED, | ||
1008 | NVT_DRIVER_NAME, (void *)nvt)) | ||
1009 | goto failure; | ||
1010 | |||
1011 | pnp_set_drvdata(pdev, nvt); | ||
1012 | nvt->pdev = pdev; | ||
1013 | |||
1014 | init_waitqueue_head(&nvt->tx.queue); | ||
1015 | |||
1016 | ret = nvt_hw_detect(nvt); | ||
1017 | if (ret) | ||
1018 | goto failure; | ||
1019 | |||
1020 | /* Initialize CIR & CIR Wake Logical Devices */ | ||
1021 | nvt_efm_enable(nvt); | ||
1022 | nvt_cir_ldev_init(nvt); | ||
1023 | nvt_cir_wake_ldev_init(nvt); | ||
1024 | nvt_efm_disable(nvt); | ||
1025 | |||
1026 | /* Initialize CIR & CIR Wake Config Registers */ | ||
1027 | nvt_cir_regs_init(nvt); | ||
1028 | nvt_cir_wake_regs_init(nvt); | ||
1029 | |||
1030 | /* Set up ir-core props */ | ||
1031 | props->priv = nvt; | ||
1032 | props->driver_type = RC_DRIVER_IR_RAW; | ||
1033 | props->allowed_protos = IR_TYPE_ALL; | ||
1034 | props->open = nvt_open; | ||
1035 | props->close = nvt_close; | ||
1036 | #if 0 | ||
1037 | props->min_timeout = XYZ; | ||
1038 | props->max_timeout = XYZ; | ||
1039 | props->timeout = XYZ; | ||
1040 | /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ | ||
1041 | props->rx_resolution = XYZ; | ||
1042 | |||
1043 | /* tx bits */ | ||
1044 | props->tx_resolution = XYZ; | ||
1045 | #endif | ||
1046 | props->tx_ir = nvt_tx_ir; | ||
1047 | props->s_tx_carrier = nvt_set_tx_carrier; | ||
1048 | |||
1049 | rdev->name = "Nuvoton w836x7hg Infrared Remote Transceiver"; | ||
1050 | rdev->id.bustype = BUS_HOST; | ||
1051 | rdev->id.vendor = PCI_VENDOR_ID_WINBOND2; | ||
1052 | rdev->id.product = nvt->chip_major; | ||
1053 | rdev->id.version = nvt->chip_minor; | ||
1054 | |||
1055 | nvt->props = props; | ||
1056 | nvt->rdev = rdev; | ||
1057 | |||
1058 | device_set_wakeup_capable(&pdev->dev, 1); | ||
1059 | device_set_wakeup_enable(&pdev->dev, 1); | ||
1060 | |||
1061 | ret = ir_input_register(rdev, RC_MAP_RC6_MCE, props, NVT_DRIVER_NAME); | ||
1062 | if (ret) | ||
1063 | goto failure; | ||
1064 | |||
1065 | nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n"); | ||
1066 | if (debug) { | ||
1067 | cir_dump_regs(nvt); | ||
1068 | cir_wake_dump_regs(nvt); | ||
1069 | } | ||
1070 | |||
1071 | return 0; | ||
1072 | |||
1073 | failure: | ||
1074 | if (nvt->cir_irq) | ||
1075 | free_irq(nvt->cir_irq, nvt); | ||
1076 | if (nvt->cir_addr) | ||
1077 | release_region(nvt->cir_addr, CIR_IOREG_LENGTH); | ||
1078 | |||
1079 | if (nvt->cir_wake_irq) | ||
1080 | free_irq(nvt->cir_wake_irq, nvt); | ||
1081 | if (nvt->cir_wake_addr) | ||
1082 | release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); | ||
1083 | |||
1084 | input_free_device(rdev); | ||
1085 | kfree(props); | ||
1086 | kfree(nvt); | ||
1087 | |||
1088 | return ret; | ||
1089 | } | ||
1090 | |||
1091 | static void __devexit nvt_remove(struct pnp_dev *pdev) | ||
1092 | { | ||
1093 | struct nvt_dev *nvt = pnp_get_drvdata(pdev); | ||
1094 | unsigned long flags; | ||
1095 | |||
1096 | spin_lock_irqsave(&nvt->nvt_lock, flags); | ||
1097 | /* disable CIR */ | ||
1098 | nvt_cir_reg_write(nvt, 0, CIR_IREN); | ||
1099 | nvt_disable_cir(nvt); | ||
1100 | /* enable CIR Wake (for IR power-on) */ | ||
1101 | nvt_enable_wake(nvt); | ||
1102 | spin_unlock_irqrestore(&nvt->nvt_lock, flags); | ||
1103 | |||
1104 | /* free resources */ | ||
1105 | free_irq(nvt->cir_irq, nvt); | ||
1106 | free_irq(nvt->cir_wake_irq, nvt); | ||
1107 | release_region(nvt->cir_addr, CIR_IOREG_LENGTH); | ||
1108 | release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); | ||
1109 | |||
1110 | ir_input_unregister(nvt->rdev); | ||
1111 | |||
1112 | kfree(nvt->props); | ||
1113 | kfree(nvt); | ||
1114 | } | ||
1115 | |||
1116 | static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) | ||
1117 | { | ||
1118 | struct nvt_dev *nvt = pnp_get_drvdata(pdev); | ||
1119 | unsigned long flags; | ||
1120 | |||
1121 | nvt_dbg("%s called", __func__); | ||
1122 | |||
1123 | /* zero out misc state tracking */ | ||
1124 | spin_lock_irqsave(&nvt->nvt_lock, flags); | ||
1125 | nvt->study_state = ST_STUDY_NONE; | ||
1126 | nvt->wake_state = ST_WAKE_NONE; | ||
1127 | spin_unlock_irqrestore(&nvt->nvt_lock, flags); | ||
1128 | |||
1129 | spin_lock_irqsave(&nvt->tx.lock, flags); | ||
1130 | nvt->tx.tx_state = ST_TX_NONE; | ||
1131 | spin_unlock_irqrestore(&nvt->tx.lock, flags); | ||
1132 | |||
1133 | /* disable all CIR interrupts */ | ||
1134 | nvt_cir_reg_write(nvt, 0, CIR_IREN); | ||
1135 | |||
1136 | nvt_efm_enable(nvt); | ||
1137 | |||
1138 | /* disable cir logical dev */ | ||
1139 | nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); | ||
1140 | nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); | ||
1141 | |||
1142 | nvt_efm_disable(nvt); | ||
1143 | |||
1144 | /* make sure wake is enabled */ | ||
1145 | nvt_enable_wake(nvt); | ||
1146 | |||
1147 | return 0; | ||
1148 | } | ||
1149 | |||
1150 | static int nvt_resume(struct pnp_dev *pdev) | ||
1151 | { | ||
1152 | int ret = 0; | ||
1153 | struct nvt_dev *nvt = pnp_get_drvdata(pdev); | ||
1154 | |||
1155 | nvt_dbg("%s called", __func__); | ||
1156 | |||
1157 | /* open interrupt */ | ||
1158 | nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); | ||
1159 | |||
1160 | /* Enable CIR logical device */ | ||
1161 | nvt_efm_enable(nvt); | ||
1162 | nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); | ||
1163 | nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); | ||
1164 | |||
1165 | nvt_efm_disable(nvt); | ||
1166 | |||
1167 | nvt_cir_regs_init(nvt); | ||
1168 | nvt_cir_wake_regs_init(nvt); | ||
1169 | |||
1170 | return ret; | ||
1171 | } | ||
1172 | |||
1173 | static void nvt_shutdown(struct pnp_dev *pdev) | ||
1174 | { | ||
1175 | struct nvt_dev *nvt = pnp_get_drvdata(pdev); | ||
1176 | nvt_enable_wake(nvt); | ||
1177 | } | ||
1178 | |||
1179 | static const struct pnp_device_id nvt_ids[] = { | ||
1180 | { "WEC0530", 0 }, /* CIR */ | ||
1181 | { "NTN0530", 0 }, /* CIR for new chip's pnp id*/ | ||
1182 | { "", 0 }, | ||
1183 | }; | ||
1184 | |||
1185 | static struct pnp_driver nvt_driver = { | ||
1186 | .name = NVT_DRIVER_NAME, | ||
1187 | .id_table = nvt_ids, | ||
1188 | .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, | ||
1189 | .probe = nvt_probe, | ||
1190 | .remove = __devexit_p(nvt_remove), | ||
1191 | .suspend = nvt_suspend, | ||
1192 | .resume = nvt_resume, | ||
1193 | .shutdown = nvt_shutdown, | ||
1194 | }; | ||
1195 | |||
1196 | int nvt_init(void) | ||
1197 | { | ||
1198 | return pnp_register_driver(&nvt_driver); | ||
1199 | } | ||
1200 | |||
1201 | void nvt_exit(void) | ||
1202 | { | ||
1203 | pnp_unregister_driver(&nvt_driver); | ||
1204 | } | ||
1205 | |||
1206 | module_param(debug, int, S_IRUGO | S_IWUSR); | ||
1207 | MODULE_PARM_DESC(debug, "Enable debugging output"); | ||
1208 | |||
1209 | MODULE_DEVICE_TABLE(pnp, nvt_ids); | ||
1210 | MODULE_DESCRIPTION("Nuvoton W83667HG-A & W83677HG-I CIR driver"); | ||
1211 | |||
1212 | MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>"); | ||
1213 | MODULE_LICENSE("GPL"); | ||
1214 | |||
1215 | module_init(nvt_init); | ||
1216 | module_exit(nvt_exit); | ||
diff --git a/drivers/media/IR/nuvoton-cir.h b/drivers/media/IR/nuvoton-cir.h new file mode 100644 index 000000000000..12bfe899fd1a --- /dev/null +++ b/drivers/media/IR/nuvoton-cir.h | |||
@@ -0,0 +1,408 @@ | |||
1 | /* | ||
2 | * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR | ||
3 | * | ||
4 | * Copyright (C) 2010 Jarod Wilson <jarod@redhat.com> | ||
5 | * Copyright (C) 2009 Nuvoton PS Team | ||
6 | * | ||
7 | * Special thanks to Nuvoton for providing hardware, spec sheets and | ||
8 | * sample code upon which portions of this driver are based. Indirect | ||
9 | * thanks also to Maxim Levitsky, whose ene_ir driver this driver is | ||
10 | * modeled after. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License as | ||
14 | * published by the Free Software Foundation; either version 2 of the | ||
15 | * License, or (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, but | ||
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
20 | * General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
25 | * USA | ||
26 | */ | ||
27 | |||
28 | #include <linux/spinlock.h> | ||
29 | #include <asm/ioctl.h> | ||
30 | |||
31 | /* platform driver name to register */ | ||
32 | #define NVT_DRIVER_NAME "nuvoton-cir" | ||
33 | |||
34 | /* debugging module parameter */ | ||
35 | static int debug; | ||
36 | |||
37 | |||
38 | #define nvt_pr(level, text, ...) \ | ||
39 | printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__) | ||
40 | |||
41 | #define nvt_dbg(text, ...) \ | ||
42 | if (debug) \ | ||
43 | printk(KERN_DEBUG \ | ||
44 | KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) | ||
45 | |||
46 | #define nvt_dbg_verbose(text, ...) \ | ||
47 | if (debug > 1) \ | ||
48 | printk(KERN_DEBUG \ | ||
49 | KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) | ||
50 | |||
51 | #define nvt_dbg_wake(text, ...) \ | ||
52 | if (debug > 2) \ | ||
53 | printk(KERN_DEBUG \ | ||
54 | KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) | ||
55 | |||
56 | |||
57 | /* | ||
58 | * Original lirc driver said min value of 76, and recommended value of 256 | ||
59 | * for the buffer length, but then used 2048. Never mind that the size of the | ||
60 | * RX FIFO is 32 bytes... So I'm using 32 for RX and 256 for TX atm, but I'm | ||
61 | * not sure if maybe that TX value is off by a factor of 8 (bits vs. bytes), | ||
62 | * and I don't have TX-capable hardware to test/debug on... | ||
63 | */ | ||
64 | #define TX_BUF_LEN 256 | ||
65 | #define RX_BUF_LEN 32 | ||
66 | |||
67 | struct nvt_dev { | ||
68 | struct pnp_dev *pdev; | ||
69 | struct input_dev *rdev; | ||
70 | struct ir_dev_props *props; | ||
71 | struct ir_raw_event rawir; | ||
72 | |||
73 | spinlock_t nvt_lock; | ||
74 | bool in_use; | ||
75 | |||
76 | /* for rx */ | ||
77 | u8 buf[RX_BUF_LEN]; | ||
78 | unsigned int pkts; | ||
79 | |||
80 | struct { | ||
81 | spinlock_t lock; | ||
82 | u8 buf[TX_BUF_LEN]; | ||
83 | unsigned int buf_count; | ||
84 | unsigned int cur_buf_num; | ||
85 | wait_queue_head_t queue; | ||
86 | u8 tx_state; | ||
87 | } tx; | ||
88 | |||
89 | /* EFER Config register index/data pair */ | ||
90 | u8 cr_efir; | ||
91 | u8 cr_efdr; | ||
92 | |||
93 | /* hardware I/O settings */ | ||
94 | unsigned long cir_addr; | ||
95 | unsigned long cir_wake_addr; | ||
96 | int cir_irq; | ||
97 | int cir_wake_irq; | ||
98 | |||
99 | /* hardware id */ | ||
100 | u8 chip_major; | ||
101 | u8 chip_minor; | ||
102 | |||
103 | /* hardware features */ | ||
104 | bool hw_learning_capable; | ||
105 | bool hw_tx_capable; | ||
106 | |||
107 | /* rx settings */ | ||
108 | bool learning_enabled; | ||
109 | bool carrier_detect_enabled; | ||
110 | |||
111 | /* track cir wake state */ | ||
112 | u8 wake_state; | ||
113 | /* for study */ | ||
114 | u8 study_state; | ||
115 | /* carrier period = 1 / frequency */ | ||
116 | u32 carrier; | ||
117 | }; | ||
118 | |||
119 | /* study states */ | ||
120 | #define ST_STUDY_NONE 0x0 | ||
121 | #define ST_STUDY_START 0x1 | ||
122 | #define ST_STUDY_CARRIER 0x2 | ||
123 | #define ST_STUDY_ALL_RECV 0x4 | ||
124 | |||
125 | /* wake states */ | ||
126 | #define ST_WAKE_NONE 0x0 | ||
127 | #define ST_WAKE_START 0x1 | ||
128 | #define ST_WAKE_FINISH 0x2 | ||
129 | |||
130 | /* receive states */ | ||
131 | #define ST_RX_WAIT_7F 0x1 | ||
132 | #define ST_RX_WAIT_HEAD 0x2 | ||
133 | #define ST_RX_WAIT_SILENT_END 0x4 | ||
134 | |||
135 | /* send states */ | ||
136 | #define ST_TX_NONE 0x0 | ||
137 | #define ST_TX_REQUEST 0x2 | ||
138 | #define ST_TX_REPLY 0x4 | ||
139 | |||
140 | /* buffer packet constants */ | ||
141 | #define BUF_PULSE_BIT 0x80 | ||
142 | #define BUF_LEN_MASK 0x7f | ||
143 | #define BUF_REPEAT_BYTE 0x70 | ||
144 | #define BUF_REPEAT_MASK 0xf0 | ||
145 | |||
146 | /* CIR settings */ | ||
147 | |||
148 | /* total length of CIR and CIR WAKE */ | ||
149 | #define CIR_IOREG_LENGTH 0x0f | ||
150 | |||
151 | /* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL (0x7d0 = 2000) */ | ||
152 | #define CIR_RX_LIMIT_COUNT 0x7d0 | ||
153 | |||
154 | /* CIR Regs */ | ||
155 | #define CIR_IRCON 0x00 | ||
156 | #define CIR_IRSTS 0x01 | ||
157 | #define CIR_IREN 0x02 | ||
158 | #define CIR_RXFCONT 0x03 | ||
159 | #define CIR_CP 0x04 | ||
160 | #define CIR_CC 0x05 | ||
161 | #define CIR_SLCH 0x06 | ||
162 | #define CIR_SLCL 0x07 | ||
163 | #define CIR_FIFOCON 0x08 | ||
164 | #define CIR_IRFIFOSTS 0x09 | ||
165 | #define CIR_SRXFIFO 0x0a | ||
166 | #define CIR_TXFCONT 0x0b | ||
167 | #define CIR_STXFIFO 0x0c | ||
168 | #define CIR_FCCH 0x0d | ||
169 | #define CIR_FCCL 0x0e | ||
170 | #define CIR_IRFSM 0x0f | ||
171 | |||
172 | /* CIR IRCON settings */ | ||
173 | #define CIR_IRCON_RECV 0x80 | ||
174 | #define CIR_IRCON_WIREN 0x40 | ||
175 | #define CIR_IRCON_TXEN 0x20 | ||
176 | #define CIR_IRCON_RXEN 0x10 | ||
177 | #define CIR_IRCON_WRXINV 0x08 | ||
178 | #define CIR_IRCON_RXINV 0x04 | ||
179 | |||
180 | #define CIR_IRCON_SAMPLE_PERIOD_SEL_1 0x00 | ||
181 | #define CIR_IRCON_SAMPLE_PERIOD_SEL_25 0x01 | ||
182 | #define CIR_IRCON_SAMPLE_PERIOD_SEL_50 0x02 | ||
183 | #define CIR_IRCON_SAMPLE_PERIOD_SEL_100 0x03 | ||
184 | |||
185 | /* FIXME: make this a runtime option */ | ||
186 | /* select sample period as 50us */ | ||
187 | #define CIR_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50 | ||
188 | |||
189 | /* CIR IRSTS settings */ | ||
190 | #define CIR_IRSTS_RDR 0x80 | ||
191 | #define CIR_IRSTS_RTR 0x40 | ||
192 | #define CIR_IRSTS_PE 0x20 | ||
193 | #define CIR_IRSTS_RFO 0x10 | ||
194 | #define CIR_IRSTS_TE 0x08 | ||
195 | #define CIR_IRSTS_TTR 0x04 | ||
196 | #define CIR_IRSTS_TFU 0x02 | ||
197 | #define CIR_IRSTS_GH 0x01 | ||
198 | |||
199 | /* CIR IREN settings */ | ||
200 | #define CIR_IREN_RDR 0x80 | ||
201 | #define CIR_IREN_RTR 0x40 | ||
202 | #define CIR_IREN_PE 0x20 | ||
203 | #define CIR_IREN_RFO 0x10 | ||
204 | #define CIR_IREN_TE 0x08 | ||
205 | #define CIR_IREN_TTR 0x04 | ||
206 | #define CIR_IREN_TFU 0x02 | ||
207 | #define CIR_IREN_GH 0x01 | ||
208 | |||
209 | /* CIR FIFOCON settings */ | ||
210 | #define CIR_FIFOCON_TXFIFOCLR 0x80 | ||
211 | |||
212 | #define CIR_FIFOCON_TX_TRIGGER_LEV_31 0x00 | ||
213 | #define CIR_FIFOCON_TX_TRIGGER_LEV_24 0x10 | ||
214 | #define CIR_FIFOCON_TX_TRIGGER_LEV_16 0x20 | ||
215 | #define CIR_FIFOCON_TX_TRIGGER_LEV_8 0x30 | ||
216 | |||
217 | /* FIXME: make this a runtime option */ | ||
218 | /* select TX trigger level as 16 */ | ||
219 | #define CIR_FIFOCON_TX_TRIGGER_LEV CIR_FIFOCON_TX_TRIGGER_LEV_16 | ||
220 | |||
221 | #define CIR_FIFOCON_RXFIFOCLR 0x08 | ||
222 | |||
223 | #define CIR_FIFOCON_RX_TRIGGER_LEV_1 0x00 | ||
224 | #define CIR_FIFOCON_RX_TRIGGER_LEV_8 0x01 | ||
225 | #define CIR_FIFOCON_RX_TRIGGER_LEV_16 0x02 | ||
226 | #define CIR_FIFOCON_RX_TRIGGER_LEV_24 0x03 | ||
227 | |||
228 | /* FIXME: make this a runtime option */ | ||
229 | /* select RX trigger level as 24 */ | ||
230 | #define CIR_FIFOCON_RX_TRIGGER_LEV CIR_FIFOCON_RX_TRIGGER_LEV_24 | ||
231 | |||
232 | /* CIR IRFIFOSTS settings */ | ||
233 | #define CIR_IRFIFOSTS_IR_PENDING 0x80 | ||
234 | #define CIR_IRFIFOSTS_RX_GS 0x40 | ||
235 | #define CIR_IRFIFOSTS_RX_FTA 0x20 | ||
236 | #define CIR_IRFIFOSTS_RX_EMPTY 0x10 | ||
237 | #define CIR_IRFIFOSTS_RX_FULL 0x08 | ||
238 | #define CIR_IRFIFOSTS_TX_FTA 0x04 | ||
239 | #define CIR_IRFIFOSTS_TX_EMPTY 0x02 | ||
240 | #define CIR_IRFIFOSTS_TX_FULL 0x01 | ||
241 | |||
242 | |||
243 | /* CIR WAKE UP Regs */ | ||
244 | #define CIR_WAKE_IRCON 0x00 | ||
245 | #define CIR_WAKE_IRSTS 0x01 | ||
246 | #define CIR_WAKE_IREN 0x02 | ||
247 | #define CIR_WAKE_FIFO_CMP_DEEP 0x03 | ||
248 | #define CIR_WAKE_FIFO_CMP_TOL 0x04 | ||
249 | #define CIR_WAKE_FIFO_COUNT 0x05 | ||
250 | #define CIR_WAKE_SLCH 0x06 | ||
251 | #define CIR_WAKE_SLCL 0x07 | ||
252 | #define CIR_WAKE_FIFOCON 0x08 | ||
253 | #define CIR_WAKE_SRXFSTS 0x09 | ||
254 | #define CIR_WAKE_SAMPLE_RX_FIFO 0x0a | ||
255 | #define CIR_WAKE_WR_FIFO_DATA 0x0b | ||
256 | #define CIR_WAKE_RD_FIFO_ONLY 0x0c | ||
257 | #define CIR_WAKE_RD_FIFO_ONLY_IDX 0x0d | ||
258 | #define CIR_WAKE_FIFO_IGNORE 0x0e | ||
259 | #define CIR_WAKE_IRFSM 0x0f | ||
260 | |||
261 | /* CIR WAKE UP IRCON settings */ | ||
262 | #define CIR_WAKE_IRCON_DEC_RST 0x80 | ||
263 | #define CIR_WAKE_IRCON_MODE1 0x40 | ||
264 | #define CIR_WAKE_IRCON_MODE0 0x20 | ||
265 | #define CIR_WAKE_IRCON_RXEN 0x10 | ||
266 | #define CIR_WAKE_IRCON_R 0x08 | ||
267 | #define CIR_WAKE_IRCON_RXINV 0x04 | ||
268 | |||
269 | /* FIXME/jarod: make this a runtime option */ | ||
270 | /* select a same sample period like cir register */ | ||
271 | #define CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50 | ||
272 | |||
273 | /* CIR WAKE IRSTS Bits */ | ||
274 | #define CIR_WAKE_IRSTS_RDR 0x80 | ||
275 | #define CIR_WAKE_IRSTS_RTR 0x40 | ||
276 | #define CIR_WAKE_IRSTS_PE 0x20 | ||
277 | #define CIR_WAKE_IRSTS_RFO 0x10 | ||
278 | #define CIR_WAKE_IRSTS_GH 0x08 | ||
279 | #define CIR_WAKE_IRSTS_IR_PENDING 0x01 | ||
280 | |||
281 | /* CIR WAKE UP IREN Bits */ | ||
282 | #define CIR_WAKE_IREN_RDR 0x80 | ||
283 | #define CIR_WAKE_IREN_RTR 0x40 | ||
284 | #define CIR_WAKE_IREN_PE 0x20 | ||
285 | #define CIR_WAKE_IREN_RFO 0x10 | ||
286 | #define CIR_WAKE_IREN_TE 0x08 | ||
287 | #define CIR_WAKE_IREN_TTR 0x04 | ||
288 | #define CIR_WAKE_IREN_TFU 0x02 | ||
289 | #define CIR_WAKE_IREN_GH 0x01 | ||
290 | |||
291 | /* CIR WAKE FIFOCON settings */ | ||
292 | #define CIR_WAKE_FIFOCON_RXFIFOCLR 0x08 | ||
293 | |||
294 | #define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67 0x00 | ||
295 | #define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_66 0x01 | ||
296 | #define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_65 0x02 | ||
297 | #define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_64 0x03 | ||
298 | |||
299 | /* FIXME: make this a runtime option */ | ||
300 | /* select WAKE UP RX trigger level as 67 */ | ||
301 | #define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67 | ||
302 | |||
303 | /* CIR WAKE SRXFSTS settings */ | ||
304 | #define CIR_WAKE_IRFIFOSTS_RX_GS 0x80 | ||
305 | #define CIR_WAKE_IRFIFOSTS_RX_FTA 0x40 | ||
306 | #define CIR_WAKE_IRFIFOSTS_RX_EMPTY 0x20 | ||
307 | #define CIR_WAKE_IRFIFOSTS_RX_FULL 0x10 | ||
308 | |||
309 | /* CIR Wake FIFO buffer is 67 bytes long */ | ||
310 | #define CIR_WAKE_FIFO_LEN 67 | ||
311 | /* CIR Wake byte comparison tolerance */ | ||
312 | #define CIR_WAKE_CMP_TOLERANCE 5 | ||
313 | |||
314 | /* | ||
315 | * Extended Function Enable Registers: | ||
316 | * Extended Function Index Register | ||
317 | * Extended Function Data Register | ||
318 | */ | ||
319 | #define CR_EFIR 0x2e | ||
320 | #define CR_EFDR 0x2f | ||
321 | |||
322 | /* Possible alternate EFER values, depends on how the chip is wired */ | ||
323 | #define CR_EFIR2 0x4e | ||
324 | #define CR_EFDR2 0x4f | ||
325 | |||
326 | /* Extended Function Mode enable/disable magic values */ | ||
327 | #define EFER_EFM_ENABLE 0x87 | ||
328 | #define EFER_EFM_DISABLE 0xaa | ||
329 | |||
330 | /* Chip IDs found in CR_CHIP_ID_{HI,LO} */ | ||
331 | #define CHIP_ID_HIGH 0xb4 | ||
332 | #define CHIP_ID_LOW 0x72 | ||
333 | #define CHIP_ID_LOW2 0x73 | ||
334 | |||
335 | /* Config regs we need to care about */ | ||
336 | #define CR_SOFTWARE_RESET 0x02 | ||
337 | #define CR_LOGICAL_DEV_SEL 0x07 | ||
338 | #define CR_CHIP_ID_HI 0x20 | ||
339 | #define CR_CHIP_ID_LO 0x21 | ||
340 | #define CR_DEV_POWER_DOWN 0x22 /* bit 2 is CIR power, default power on */ | ||
341 | #define CR_OUTPUT_PIN_SEL 0x27 | ||
342 | #define CR_LOGICAL_DEV_EN 0x30 /* valid for all logical devices */ | ||
343 | /* next three regs valid for both the CIR and CIR_WAKE logical devices */ | ||
344 | #define CR_CIR_BASE_ADDR_HI 0x60 | ||
345 | #define CR_CIR_BASE_ADDR_LO 0x61 | ||
346 | #define CR_CIR_IRQ_RSRC 0x70 | ||
347 | /* next three regs valid only for ACPI logical dev */ | ||
348 | #define CR_ACPI_CIR_WAKE 0xe0 | ||
349 | #define CR_ACPI_IRQ_EVENTS 0xf6 | ||
350 | #define CR_ACPI_IRQ_EVENTS2 0xf7 | ||
351 | |||
352 | /* Logical devices that we need to care about */ | ||
353 | #define LOGICAL_DEV_LPT 0x01 | ||
354 | #define LOGICAL_DEV_CIR 0x06 | ||
355 | #define LOGICAL_DEV_ACPI 0x0a | ||
356 | #define LOGICAL_DEV_CIR_WAKE 0x0e | ||
357 | |||
358 | #define LOGICAL_DEV_DISABLE 0x00 | ||
359 | #define LOGICAL_DEV_ENABLE 0x01 | ||
360 | |||
361 | #define CIR_WAKE_ENABLE_BIT 0x08 | ||
362 | #define CIR_INTR_MOUSE_IRQ_BIT 0x80 | ||
363 | #define PME_INTR_CIR_PASS_BIT 0x08 | ||
364 | |||
365 | #define OUTPUT_PIN_SEL_MASK 0xbc | ||
366 | #define OUTPUT_ENABLE_CIR 0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */ | ||
367 | #define OUTPUT_ENABLE_CIRWB 0x40 /* enable wide-band sensor */ | ||
368 | |||
369 | /* MCE CIR signal length, related on sample period */ | ||
370 | |||
371 | /* MCE CIR controller signal length: about 43ms | ||
372 | * 43ms / 50us (sample period) * 0.85 (inaccuracy) | ||
373 | */ | ||
374 | #define CONTROLLER_BUF_LEN_MIN 830 | ||
375 | |||
376 | /* MCE CIR keyboard signal length: about 26ms | ||
377 | * 26ms / 50us (sample period) * 0.85 (inaccuracy) | ||
378 | */ | ||
379 | #define KEYBOARD_BUF_LEN_MAX 650 | ||
380 | #define KEYBOARD_BUF_LEN_MIN 610 | ||
381 | |||
382 | /* MCE CIR mouse signal length: about 24ms | ||
383 | * 24ms / 50us (sample period) * 0.85 (inaccuracy) | ||
384 | */ | ||
385 | #define MOUSE_BUF_LEN_MIN 565 | ||
386 | |||
387 | #define CIR_SAMPLE_PERIOD 50 | ||
388 | #define CIR_SAMPLE_LOW_INACCURACY 0.85 | ||
389 | |||
390 | /* MAX silence time that driver will sent to lirc */ | ||
391 | #define MAX_SILENCE_TIME 60000 | ||
392 | |||
393 | #if CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_100 | ||
394 | #define SAMPLE_PERIOD 100 | ||
395 | |||
396 | #elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_50 | ||
397 | #define SAMPLE_PERIOD 50 | ||
398 | |||
399 | #elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_25 | ||
400 | #define SAMPLE_PERIOD 25 | ||
401 | |||
402 | #else | ||
403 | #define SAMPLE_PERIOD 1 | ||
404 | #endif | ||
405 | |||
406 | /* as VISTA MCE definition, valid carrier value */ | ||
407 | #define MAX_CARRIER 60000 | ||
408 | #define MIN_CARRIER 30000 | ||