xref: /openbmc/linux/drivers/media/rc/winbond-cir.c (revision 4800cd83)
1 /*
2  *  winbond-cir.c - Driver for the Consumer IR functionality of Winbond
3  *                  SuperI/O chips.
4  *
5  *  Currently supports the Winbond WPCD376i chip (PNP id WEC1022), but
6  *  could probably support others (Winbond WEC102X, NatSemi, etc)
7  *  with minor modifications.
8  *
9  *  Original Author: David H�rdeman <david@hardeman.nu>
10  *     Copyright (C) 2009 - 2010 David H�rdeman <david@hardeman.nu>
11  *
12  *  Dedicated to my daughter Matilda, without whose loving attention this
13  *  driver would have been finished in half the time and with a fraction
14  *  of the bugs.
15  *
16  *  Written using:
17  *    o Winbond WPCD376I datasheet helpfully provided by Jesse Barnes at Intel
18  *    o NatSemi PC87338/PC97338 datasheet (for the serial port stuff)
19  *    o DSDT dumps
20  *
21  *  Supported features:
22  *    o Wake-On-CIR functionality
23  *
24  *  To do:
25  *    o Learning
26  *    o IR Transmit
27  *
28  *  This program is free software; you can redistribute it and/or modify
29  *  it under the terms of the GNU General Public License as published by
30  *  the Free Software Foundation; either version 2 of the License, or
31  *  (at your option) any later version.
32  *
33  *  This program is distributed in the hope that it will be useful,
34  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
35  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
36  *  GNU General Public License for more details.
37  *
38  *  You should have received a copy of the GNU General Public License
39  *  along with this program; if not, write to the Free Software
40  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
41  */
42 
43 #include <linux/module.h>
44 #include <linux/pnp.h>
45 #include <linux/interrupt.h>
46 #include <linux/timer.h>
47 #include <linux/leds.h>
48 #include <linux/spinlock.h>
49 #include <linux/pci_ids.h>
50 #include <linux/io.h>
51 #include <linux/bitrev.h>
52 #include <linux/slab.h>
53 #include <media/rc-core.h>
54 
55 #define DRVNAME "winbond-cir"
56 
57 /* CEIR Wake-Up Registers, relative to data->wbase                      */
58 #define WBCIR_REG_WCEIR_CTL	0x03 /* CEIR Receiver Control		*/
59 #define WBCIR_REG_WCEIR_STS	0x04 /* CEIR Receiver Status		*/
60 #define WBCIR_REG_WCEIR_EV_EN	0x05 /* CEIR Receiver Event Enable	*/
61 #define WBCIR_REG_WCEIR_CNTL	0x06 /* CEIR Receiver Counter Low	*/
62 #define WBCIR_REG_WCEIR_CNTH	0x07 /* CEIR Receiver Counter High	*/
63 #define WBCIR_REG_WCEIR_INDEX	0x08 /* CEIR Receiver Index		*/
64 #define WBCIR_REG_WCEIR_DATA	0x09 /* CEIR Receiver Data		*/
65 #define WBCIR_REG_WCEIR_CSL	0x0A /* CEIR Re. Compare Strlen		*/
66 #define WBCIR_REG_WCEIR_CFG1	0x0B /* CEIR Re. Configuration 1	*/
67 #define WBCIR_REG_WCEIR_CFG2	0x0C /* CEIR Re. Configuration 2	*/
68 
69 /* CEIR Enhanced Functionality Registers, relative to data->ebase       */
70 #define WBCIR_REG_ECEIR_CTS	0x00 /* Enhanced IR Control Status	*/
71 #define WBCIR_REG_ECEIR_CCTL	0x01 /* Infrared Counter Control	*/
72 #define WBCIR_REG_ECEIR_CNT_LO	0x02 /* Infrared Counter LSB		*/
73 #define WBCIR_REG_ECEIR_CNT_HI	0x03 /* Infrared Counter MSB		*/
74 #define WBCIR_REG_ECEIR_IREM	0x04 /* Infrared Emitter Status		*/
75 
76 /* SP3 Banked Registers, relative to data->sbase                        */
77 #define WBCIR_REG_SP3_BSR	0x03 /* Bank Select, all banks		*/
78 				      /* Bank 0				*/
79 #define WBCIR_REG_SP3_RXDATA	0x00 /* FIFO RX data (r)		*/
80 #define WBCIR_REG_SP3_TXDATA	0x00 /* FIFO TX data (w)		*/
81 #define WBCIR_REG_SP3_IER	0x01 /* Interrupt Enable		*/
82 #define WBCIR_REG_SP3_EIR	0x02 /* Event Identification (r)	*/
83 #define WBCIR_REG_SP3_FCR	0x02 /* FIFO Control (w)		*/
84 #define WBCIR_REG_SP3_MCR	0x04 /* Mode Control			*/
85 #define WBCIR_REG_SP3_LSR	0x05 /* Link Status			*/
86 #define WBCIR_REG_SP3_MSR	0x06 /* Modem Status			*/
87 #define WBCIR_REG_SP3_ASCR	0x07 /* Aux Status and Control		*/
88 				      /* Bank 2				*/
89 #define WBCIR_REG_SP3_BGDL	0x00 /* Baud Divisor LSB		*/
90 #define WBCIR_REG_SP3_BGDH	0x01 /* Baud Divisor MSB		*/
91 #define WBCIR_REG_SP3_EXCR1	0x02 /* Extended Control 1		*/
92 #define WBCIR_REG_SP3_EXCR2	0x04 /* Extended Control 2		*/
93 #define WBCIR_REG_SP3_TXFLV	0x06 /* TX FIFO Level			*/
94 #define WBCIR_REG_SP3_RXFLV	0x07 /* RX FIFO Level			*/
95 				      /* Bank 3				*/
96 #define WBCIR_REG_SP3_MRID	0x00 /* Module Identification		*/
97 #define WBCIR_REG_SP3_SH_LCR	0x01 /* LCR Shadow			*/
98 #define WBCIR_REG_SP3_SH_FCR	0x02 /* FCR Shadow			*/
99 				      /* Bank 4				*/
100 #define WBCIR_REG_SP3_IRCR1	0x02 /* Infrared Control 1		*/
101 				      /* Bank 5				*/
102 #define WBCIR_REG_SP3_IRCR2	0x04 /* Infrared Control 2		*/
103 				      /* Bank 6				*/
104 #define WBCIR_REG_SP3_IRCR3	0x00 /* Infrared Control 3		*/
105 #define WBCIR_REG_SP3_SIR_PW	0x02 /* SIR Pulse Width			*/
106 				      /* Bank 7				*/
107 #define WBCIR_REG_SP3_IRRXDC	0x00 /* IR RX Demod Control		*/
108 #define WBCIR_REG_SP3_IRTXMC	0x01 /* IR TX Mod Control		*/
109 #define WBCIR_REG_SP3_RCCFG	0x02 /* CEIR Config			*/
110 #define WBCIR_REG_SP3_IRCFG1	0x04 /* Infrared Config 1		*/
111 #define WBCIR_REG_SP3_IRCFG4	0x07 /* Infrared Config 4		*/
112 
113 /*
114  * Magic values follow
115  */
116 
117 /* No interrupts for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */
118 #define WBCIR_IRQ_NONE		0x00
119 /* RX data bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */
120 #define WBCIR_IRQ_RX		0x01
121 /* Over/Under-flow bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */
122 #define WBCIR_IRQ_ERR		0x04
123 /* Led enable/disable bit for WBCIR_REG_ECEIR_CTS */
124 #define WBCIR_LED_ENABLE	0x80
125 /* RX data available bit for WBCIR_REG_SP3_LSR */
126 #define WBCIR_RX_AVAIL		0x01
127 /* RX disable bit for WBCIR_REG_SP3_ASCR */
128 #define WBCIR_RX_DISABLE	0x20
129 /* Extended mode enable bit for WBCIR_REG_SP3_EXCR1 */
130 #define WBCIR_EXT_ENABLE	0x01
131 /* Select compare register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */
132 #define WBCIR_REGSEL_COMPARE	0x10
133 /* Select mask register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */
134 #define WBCIR_REGSEL_MASK	0x20
135 /* Starting address of selected register in WBCIR_REG_WCEIR_INDEX */
136 #define WBCIR_REG_ADDR0		0x00
137 
138 /* Valid banks for the SP3 UART */
139 enum wbcir_bank {
140 	WBCIR_BANK_0          = 0x00,
141 	WBCIR_BANK_1          = 0x80,
142 	WBCIR_BANK_2          = 0xE0,
143 	WBCIR_BANK_3          = 0xE4,
144 	WBCIR_BANK_4          = 0xE8,
145 	WBCIR_BANK_5          = 0xEC,
146 	WBCIR_BANK_6          = 0xF0,
147 	WBCIR_BANK_7          = 0xF4,
148 };
149 
150 /* Supported power-on IR Protocols */
151 enum wbcir_protocol {
152 	IR_PROTOCOL_RC5          = 0x0,
153 	IR_PROTOCOL_NEC          = 0x1,
154 	IR_PROTOCOL_RC6          = 0x2,
155 };
156 
157 /* Misc */
158 #define WBCIR_NAME	"Winbond CIR"
159 #define WBCIR_ID_FAMILY          0xF1 /* Family ID for the WPCD376I	*/
160 #define	WBCIR_ID_CHIP            0x04 /* Chip ID for the WPCD376I	*/
161 #define INVALID_SCANCODE   0x7FFFFFFF /* Invalid with all protos	*/
162 #define WAKEUP_IOMEM_LEN         0x10 /* Wake-Up I/O Reg Len		*/
163 #define EHFUNC_IOMEM_LEN         0x10 /* Enhanced Func I/O Reg Len	*/
164 #define SP_IOMEM_LEN             0x08 /* Serial Port 3 (IR) Reg Len	*/
165 
166 /* Per-device data */
167 struct wbcir_data {
168 	spinlock_t spinlock;
169 
170 	unsigned long wbase;        /* Wake-Up Baseaddr		*/
171 	unsigned long ebase;        /* Enhanced Func. Baseaddr	*/
172 	unsigned long sbase;        /* Serial Port Baseaddr	*/
173 	unsigned int  irq;          /* Serial Port IRQ		*/
174 
175 	struct rc_dev *dev;
176 
177 	struct led_trigger *rxtrigger;
178 	struct led_trigger *txtrigger;
179 	struct led_classdev led;
180 
181 	/* RX irdata state */
182 	bool irdata_active;
183 	bool irdata_error;
184 	struct ir_raw_event ev;
185 };
186 
187 static enum wbcir_protocol protocol = IR_PROTOCOL_RC6;
188 module_param(protocol, uint, 0444);
189 MODULE_PARM_DESC(protocol, "IR protocol to use for the power-on command "
190 		 "(0 = RC5, 1 = NEC, 2 = RC6A, default)");
191 
192 static int invert; /* default = 0 */
193 module_param(invert, bool, 0444);
194 MODULE_PARM_DESC(invert, "Invert the signal from the IR receiver");
195 
196 static unsigned int wake_sc = 0x800F040C;
197 module_param(wake_sc, uint, 0644);
198 MODULE_PARM_DESC(wake_sc, "Scancode of the power-on IR command");
199 
200 static unsigned int wake_rc6mode = 6;
201 module_param(wake_rc6mode, uint, 0644);
202 MODULE_PARM_DESC(wake_rc6mode, "RC6 mode for the power-on command "
203 		 "(0 = 0, 6 = 6A, default)");
204 
205 
206 
207 /*****************************************************************************
208  *
209  * UTILITY FUNCTIONS
210  *
211  *****************************************************************************/
212 
213 /* Caller needs to hold wbcir_lock */
214 static void
215 wbcir_set_bits(unsigned long addr, u8 bits, u8 mask)
216 {
217 	u8 val;
218 
219 	val = inb(addr);
220 	val = ((val & ~mask) | (bits & mask));
221 	outb(val, addr);
222 }
223 
224 /* Selects the register bank for the serial port */
225 static inline void
226 wbcir_select_bank(struct wbcir_data *data, enum wbcir_bank bank)
227 {
228 	outb(bank, data->sbase + WBCIR_REG_SP3_BSR);
229 }
230 
231 static enum led_brightness
232 wbcir_led_brightness_get(struct led_classdev *led_cdev)
233 {
234 	struct wbcir_data *data = container_of(led_cdev,
235 					       struct wbcir_data,
236 					       led);
237 
238 	if (inb(data->ebase + WBCIR_REG_ECEIR_CTS) & WBCIR_LED_ENABLE)
239 		return LED_FULL;
240 	else
241 		return LED_OFF;
242 }
243 
244 static void
245 wbcir_led_brightness_set(struct led_classdev *led_cdev,
246 			 enum led_brightness brightness)
247 {
248 	struct wbcir_data *data = container_of(led_cdev,
249 					       struct wbcir_data,
250 					       led);
251 
252 	wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CTS,
253 		       brightness == LED_OFF ? 0x00 : WBCIR_LED_ENABLE,
254 		       WBCIR_LED_ENABLE);
255 }
256 
257 /* Manchester encodes bits to RC6 message cells (see wbcir_shutdown) */
258 static u8
259 wbcir_to_rc6cells(u8 val)
260 {
261 	u8 coded = 0x00;
262 	int i;
263 
264 	val &= 0x0F;
265 	for (i = 0; i < 4; i++) {
266 		if (val & 0x01)
267 			coded |= 0x02 << (i * 2);
268 		else
269 			coded |= 0x01 << (i * 2);
270 		val >>= 1;
271 	}
272 
273 	return coded;
274 }
275 
276 /*****************************************************************************
277  *
278  * INTERRUPT FUNCTIONS
279  *
280  *****************************************************************************/
281 
282 static irqreturn_t
283 wbcir_irq_handler(int irqno, void *cookie)
284 {
285 	struct pnp_dev *device = cookie;
286 	struct wbcir_data *data = pnp_get_drvdata(device);
287 	unsigned long flags;
288 	u8 irdata[8];
289 	u8 disable = true;
290 	u8 status;
291 	int i;
292 
293 	spin_lock_irqsave(&data->spinlock, flags);
294 
295 	wbcir_select_bank(data, WBCIR_BANK_0);
296 
297 	status = inb(data->sbase + WBCIR_REG_SP3_EIR);
298 
299 	if (!(status & (WBCIR_IRQ_RX | WBCIR_IRQ_ERR))) {
300 		spin_unlock_irqrestore(&data->spinlock, flags);
301 		return IRQ_NONE;
302 	}
303 
304 	/* Check for e.g. buffer overflow */
305 	if (status & WBCIR_IRQ_ERR) {
306 		data->irdata_error = true;
307 		ir_raw_event_reset(data->dev);
308 	}
309 
310 	if (!(status & WBCIR_IRQ_RX))
311 		goto out;
312 
313 	if (!data->irdata_active) {
314 		data->irdata_active = true;
315 		led_trigger_event(data->rxtrigger, LED_FULL);
316 	}
317 
318 	/* Since RXHDLEV is set, at least 8 bytes are in the FIFO */
319 	insb(data->sbase + WBCIR_REG_SP3_RXDATA, &irdata[0], 8);
320 
321 	for (i = 0; i < 8; i++) {
322 		u8 pulse;
323 		u32 duration;
324 
325 		if (irdata[i] != 0xFF && irdata[i] != 0x00)
326 			disable = false;
327 
328 		if (data->irdata_error)
329 			continue;
330 
331 		pulse = irdata[i] & 0x80 ? false : true;
332 		duration = (irdata[i] & 0x7F) * 10000; /* ns */
333 
334 		if (data->ev.pulse != pulse) {
335 			if (data->ev.duration != 0) {
336 				ir_raw_event_store(data->dev, &data->ev);
337 				data->ev.duration = 0;
338 			}
339 
340 			data->ev.pulse = pulse;
341 		}
342 
343 		data->ev.duration += duration;
344 	}
345 
346 	if (disable) {
347 		if (data->ev.duration != 0 && !data->irdata_error) {
348 			ir_raw_event_store(data->dev, &data->ev);
349 			data->ev.duration = 0;
350 		}
351 
352 		/* Set RXINACTIVE */
353 		outb(WBCIR_RX_DISABLE, data->sbase + WBCIR_REG_SP3_ASCR);
354 
355 		/* Drain the FIFO */
356 		while (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_AVAIL)
357 			inb(data->sbase + WBCIR_REG_SP3_RXDATA);
358 
359 		ir_raw_event_reset(data->dev);
360 		data->irdata_error = false;
361 		data->irdata_active = false;
362 		led_trigger_event(data->rxtrigger, LED_OFF);
363 	}
364 
365 	ir_raw_event_handle(data->dev);
366 
367 out:
368 	spin_unlock_irqrestore(&data->spinlock, flags);
369 	return IRQ_HANDLED;
370 }
371 
372 
373 
374 /*****************************************************************************
375  *
376  * SETUP/INIT/SUSPEND/RESUME FUNCTIONS
377  *
378  *****************************************************************************/
379 
380 static void
381 wbcir_shutdown(struct pnp_dev *device)
382 {
383 	struct device *dev = &device->dev;
384 	struct wbcir_data *data = pnp_get_drvdata(device);
385 	int do_wake = 1;
386 	u8 match[11];
387 	u8 mask[11];
388 	u8 rc6_csl = 0;
389 	int i;
390 
391 	memset(match, 0, sizeof(match));
392 	memset(mask, 0, sizeof(mask));
393 
394 	if (wake_sc == INVALID_SCANCODE || !device_may_wakeup(dev)) {
395 		do_wake = 0;
396 		goto finish;
397 	}
398 
399 	switch (protocol) {
400 	case IR_PROTOCOL_RC5:
401 		if (wake_sc > 0xFFF) {
402 			do_wake = 0;
403 			dev_err(dev, "RC5 - Invalid wake scancode\n");
404 			break;
405 		}
406 
407 		/* Mask = 13 bits, ex toggle */
408 		mask[0] = 0xFF;
409 		mask[1] = 0x17;
410 
411 		match[0]  = (wake_sc & 0x003F);      /* 6 command bits */
412 		match[0] |= (wake_sc & 0x0180) >> 1; /* 2 address bits */
413 		match[1]  = (wake_sc & 0x0E00) >> 9; /* 3 address bits */
414 		if (!(wake_sc & 0x0040))             /* 2nd start bit  */
415 			match[1] |= 0x10;
416 
417 		break;
418 
419 	case IR_PROTOCOL_NEC:
420 		if (wake_sc > 0xFFFFFF) {
421 			do_wake = 0;
422 			dev_err(dev, "NEC - Invalid wake scancode\n");
423 			break;
424 		}
425 
426 		mask[0] = mask[1] = mask[2] = mask[3] = 0xFF;
427 
428 		match[1] = bitrev8((wake_sc & 0xFF));
429 		match[0] = ~match[1];
430 
431 		match[3] = bitrev8((wake_sc & 0xFF00) >> 8);
432 		if (wake_sc > 0xFFFF)
433 			match[2] = bitrev8((wake_sc & 0xFF0000) >> 16);
434 		else
435 			match[2] = ~match[3];
436 
437 		break;
438 
439 	case IR_PROTOCOL_RC6:
440 
441 		if (wake_rc6mode == 0) {
442 			if (wake_sc > 0xFFFF) {
443 				do_wake = 0;
444 				dev_err(dev, "RC6 - Invalid wake scancode\n");
445 				break;
446 			}
447 
448 			/* Command */
449 			match[0] = wbcir_to_rc6cells(wake_sc >>  0);
450 			mask[0]  = 0xFF;
451 			match[1] = wbcir_to_rc6cells(wake_sc >>  4);
452 			mask[1]  = 0xFF;
453 
454 			/* Address */
455 			match[2] = wbcir_to_rc6cells(wake_sc >>  8);
456 			mask[2]  = 0xFF;
457 			match[3] = wbcir_to_rc6cells(wake_sc >> 12);
458 			mask[3]  = 0xFF;
459 
460 			/* Header */
461 			match[4] = 0x50; /* mode1 = mode0 = 0, ignore toggle */
462 			mask[4]  = 0xF0;
463 			match[5] = 0x09; /* start bit = 1, mode2 = 0 */
464 			mask[5]  = 0x0F;
465 
466 			rc6_csl = 44;
467 
468 		} else if (wake_rc6mode == 6) {
469 			i = 0;
470 
471 			/* Command */
472 			match[i]  = wbcir_to_rc6cells(wake_sc >>  0);
473 			mask[i++] = 0xFF;
474 			match[i]  = wbcir_to_rc6cells(wake_sc >>  4);
475 			mask[i++] = 0xFF;
476 
477 			/* Address + Toggle */
478 			match[i]  = wbcir_to_rc6cells(wake_sc >>  8);
479 			mask[i++] = 0xFF;
480 			match[i]  = wbcir_to_rc6cells(wake_sc >> 12);
481 			mask[i++] = 0x3F;
482 
483 			/* Customer bits 7 - 0 */
484 			match[i]  = wbcir_to_rc6cells(wake_sc >> 16);
485 			mask[i++] = 0xFF;
486 			match[i]  = wbcir_to_rc6cells(wake_sc >> 20);
487 			mask[i++] = 0xFF;
488 
489 			if (wake_sc & 0x80000000) {
490 				/* Customer range bit and bits 15 - 8 */
491 				match[i]  = wbcir_to_rc6cells(wake_sc >> 24);
492 				mask[i++] = 0xFF;
493 				match[i]  = wbcir_to_rc6cells(wake_sc >> 28);
494 				mask[i++] = 0xFF;
495 				rc6_csl = 76;
496 			} else if (wake_sc <= 0x007FFFFF) {
497 				rc6_csl = 60;
498 			} else {
499 				do_wake = 0;
500 				dev_err(dev, "RC6 - Invalid wake scancode\n");
501 				break;
502 			}
503 
504 			/* Header */
505 			match[i]  = 0x93; /* mode1 = mode0 = 1, submode = 0 */
506 			mask[i++] = 0xFF;
507 			match[i]  = 0x0A; /* start bit = 1, mode2 = 1 */
508 			mask[i++] = 0x0F;
509 
510 		} else {
511 			do_wake = 0;
512 			dev_err(dev, "RC6 - Invalid wake mode\n");
513 		}
514 
515 		break;
516 
517 	default:
518 		do_wake = 0;
519 		break;
520 	}
521 
522 finish:
523 	if (do_wake) {
524 		/* Set compare and compare mask */
525 		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX,
526 			       WBCIR_REGSEL_COMPARE | WBCIR_REG_ADDR0,
527 			       0x3F);
528 		outsb(data->wbase + WBCIR_REG_WCEIR_DATA, match, 11);
529 		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX,
530 			       WBCIR_REGSEL_MASK | WBCIR_REG_ADDR0,
531 			       0x3F);
532 		outsb(data->wbase + WBCIR_REG_WCEIR_DATA, mask, 11);
533 
534 		/* RC6 Compare String Len */
535 		outb(rc6_csl, data->wbase + WBCIR_REG_WCEIR_CSL);
536 
537 		/* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */
538 		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17);
539 
540 		/* Clear BUFF_EN, Clear END_EN, Set MATCH_EN */
541 		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x01, 0x07);
542 
543 		/* Set CEIR_EN */
544 		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x01, 0x01);
545 
546 	} else {
547 		/* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */
548 		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
549 
550 		/* Clear CEIR_EN */
551 		wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01);
552 	}
553 
554 	/* Disable interrupts */
555 	wbcir_select_bank(data, WBCIR_BANK_0);
556 	outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER);
557 
558 	/* Disable LED */
559 	data->irdata_active = false;
560 	led_trigger_event(data->rxtrigger, LED_OFF);
561 
562 	/*
563 	 * ACPI will set the HW disable bit for SP3 which means that the
564 	 * output signals are left in an undefined state which may cause
565 	 * spurious interrupts which we need to ignore until the hardware
566 	 * is reinitialized.
567 	 */
568 	disable_irq(data->irq);
569 }
570 
571 static int
572 wbcir_suspend(struct pnp_dev *device, pm_message_t state)
573 {
574 	wbcir_shutdown(device);
575 	return 0;
576 }
577 
578 static void
579 wbcir_init_hw(struct wbcir_data *data)
580 {
581 	u8 tmp;
582 
583 	/* Disable interrupts */
584 	wbcir_select_bank(data, WBCIR_BANK_0);
585 	outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER);
586 
587 	/* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */
588 	tmp = protocol << 4;
589 	if (invert)
590 		tmp |= 0x08;
591 	outb(tmp, data->wbase + WBCIR_REG_WCEIR_CTL);
592 
593 	/* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */
594 	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17);
595 
596 	/* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */
597 	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
598 
599 	/* Set RC5 cell time to correspond to 36 kHz */
600 	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CFG1, 0x4A, 0x7F);
601 
602 	/* Set IRTX_INV */
603 	if (invert)
604 		outb(0x04, data->ebase + WBCIR_REG_ECEIR_CCTL);
605 	else
606 		outb(0x00, data->ebase + WBCIR_REG_ECEIR_CCTL);
607 
608 	/*
609 	 * Clear IR LED, set SP3 clock to 24Mhz
610 	 * set SP3_IRRX_SW to binary 01, helpfully not documented
611 	 */
612 	outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS);
613 
614 	/* Enable extended mode */
615 	wbcir_select_bank(data, WBCIR_BANK_2);
616 	outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1);
617 
618 	/*
619 	 * Configure baud generator, IR data will be sampled at
620 	 * a bitrate of: (24Mhz * prescaler) / (divisor * 16).
621 	 *
622 	 * The ECIR registers include a flag to change the
623 	 * 24Mhz clock freq to 48Mhz.
624 	 *
625 	 * It's not documented in the specs, but fifo levels
626 	 * other than 16 seems to be unsupported.
627 	 */
628 
629 	/* prescaler 1.0, tx/rx fifo lvl 16 */
630 	outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2);
631 
632 	/* Set baud divisor to generate one byte per bit/cell */
633 	switch (protocol) {
634 	case IR_PROTOCOL_RC5:
635 		outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL);
636 		break;
637 	case IR_PROTOCOL_RC6:
638 		outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL);
639 		break;
640 	case IR_PROTOCOL_NEC:
641 		outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL);
642 		break;
643 	}
644 	outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH);
645 
646 	/* Set CEIR mode */
647 	wbcir_select_bank(data, WBCIR_BANK_0);
648 	outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR);
649 	inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */
650 	inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */
651 
652 	/* Disable RX demod, run-length encoding/decoding, set freq span */
653 	wbcir_select_bank(data, WBCIR_BANK_7);
654 	outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG);
655 
656 	/* Disable timer */
657 	wbcir_select_bank(data, WBCIR_BANK_4);
658 	outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1);
659 
660 	/* Enable MSR interrupt, Clear AUX_IRX */
661 	wbcir_select_bank(data, WBCIR_BANK_5);
662 	outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2);
663 
664 	/* Disable CRC */
665 	wbcir_select_bank(data, WBCIR_BANK_6);
666 	outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3);
667 
668 	/* Set RX/TX (de)modulation freq, not really used */
669 	wbcir_select_bank(data, WBCIR_BANK_7);
670 	outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC);
671 	outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC);
672 
673 	/* Set invert and pin direction */
674 	if (invert)
675 		outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4);
676 	else
677 		outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4);
678 
679 	/* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */
680 	wbcir_select_bank(data, WBCIR_BANK_0);
681 	outb(0x97, data->sbase + WBCIR_REG_SP3_FCR);
682 
683 	/* Clear AUX status bits */
684 	outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR);
685 
686 	/* Clear IR decoding state */
687 	data->irdata_active = false;
688 	led_trigger_event(data->rxtrigger, LED_OFF);
689 	data->irdata_error = false;
690 	data->ev.duration = 0;
691 	ir_raw_event_reset(data->dev);
692 	ir_raw_event_handle(data->dev);
693 
694 	/* Enable interrupts */
695 	outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER);
696 }
697 
698 static int
699 wbcir_resume(struct pnp_dev *device)
700 {
701 	struct wbcir_data *data = pnp_get_drvdata(device);
702 
703 	wbcir_init_hw(data);
704 	enable_irq(data->irq);
705 
706 	return 0;
707 }
708 
709 static int __devinit
710 wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
711 {
712 	struct device *dev = &device->dev;
713 	struct wbcir_data *data;
714 	int err;
715 
716 	if (!(pnp_port_len(device, 0) == EHFUNC_IOMEM_LEN &&
717 	      pnp_port_len(device, 1) == WAKEUP_IOMEM_LEN &&
718 	      pnp_port_len(device, 2) == SP_IOMEM_LEN)) {
719 		dev_err(dev, "Invalid resources\n");
720 		return -ENODEV;
721 	}
722 
723 	data = kzalloc(sizeof(*data), GFP_KERNEL);
724 	if (!data) {
725 		err = -ENOMEM;
726 		goto exit;
727 	}
728 
729 	pnp_set_drvdata(device, data);
730 
731 	spin_lock_init(&data->spinlock);
732 	data->ebase = pnp_port_start(device, 0);
733 	data->wbase = pnp_port_start(device, 1);
734 	data->sbase = pnp_port_start(device, 2);
735 	data->irq = pnp_irq(device, 0);
736 
737 	if (data->wbase == 0 || data->ebase == 0 ||
738 	    data->sbase == 0 || data->irq == 0) {
739 		err = -ENODEV;
740 		dev_err(dev, "Invalid resources\n");
741 		goto exit_free_data;
742 	}
743 
744 	dev_dbg(&device->dev, "Found device "
745 		"(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n",
746 		data->wbase, data->ebase, data->sbase, data->irq);
747 
748 	if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) {
749 		dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
750 			data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1);
751 		err = -EBUSY;
752 		goto exit_free_data;
753 	}
754 
755 	if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) {
756 		dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
757 			data->ebase, data->ebase + EHFUNC_IOMEM_LEN - 1);
758 		err = -EBUSY;
759 		goto exit_release_wbase;
760 	}
761 
762 	if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) {
763 		dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
764 			data->sbase, data->sbase + SP_IOMEM_LEN - 1);
765 		err = -EBUSY;
766 		goto exit_release_ebase;
767 	}
768 
769 	err = request_irq(data->irq, wbcir_irq_handler,
770 			  IRQF_DISABLED, DRVNAME, device);
771 	if (err) {
772 		dev_err(dev, "Failed to claim IRQ %u\n", data->irq);
773 		err = -EBUSY;
774 		goto exit_release_sbase;
775 	}
776 
777 	led_trigger_register_simple("cir-tx", &data->txtrigger);
778 	if (!data->txtrigger) {
779 		err = -ENOMEM;
780 		goto exit_free_irq;
781 	}
782 
783 	led_trigger_register_simple("cir-rx", &data->rxtrigger);
784 	if (!data->rxtrigger) {
785 		err = -ENOMEM;
786 		goto exit_unregister_txtrigger;
787 	}
788 
789 	data->led.name = "cir::activity";
790 	data->led.default_trigger = "cir-rx";
791 	data->led.brightness_set = wbcir_led_brightness_set;
792 	data->led.brightness_get = wbcir_led_brightness_get;
793 	err = led_classdev_register(&device->dev, &data->led);
794 	if (err)
795 		goto exit_unregister_rxtrigger;
796 
797 	data->dev = rc_allocate_device();
798 	if (!data->dev) {
799 		err = -ENOMEM;
800 		goto exit_unregister_led;
801 	}
802 
803 	data->dev->driver_name = WBCIR_NAME;
804 	data->dev->input_name = WBCIR_NAME;
805 	data->dev->input_phys = "wbcir/cir0";
806 	data->dev->input_id.bustype = BUS_HOST;
807 	data->dev->input_id.vendor = PCI_VENDOR_ID_WINBOND;
808 	data->dev->input_id.product = WBCIR_ID_FAMILY;
809 	data->dev->input_id.version = WBCIR_ID_CHIP;
810 	data->dev->priv = data;
811 	data->dev->dev.parent = &device->dev;
812 
813 	err = rc_register_device(data->dev);
814 	if (err)
815 		goto exit_free_rc;
816 
817 	device_init_wakeup(&device->dev, 1);
818 
819 	wbcir_init_hw(data);
820 
821 	return 0;
822 
823 exit_free_rc:
824 	rc_free_device(data->dev);
825 exit_unregister_led:
826 	led_classdev_unregister(&data->led);
827 exit_unregister_rxtrigger:
828 	led_trigger_unregister_simple(data->rxtrigger);
829 exit_unregister_txtrigger:
830 	led_trigger_unregister_simple(data->txtrigger);
831 exit_free_irq:
832 	free_irq(data->irq, device);
833 exit_release_sbase:
834 	release_region(data->sbase, SP_IOMEM_LEN);
835 exit_release_ebase:
836 	release_region(data->ebase, EHFUNC_IOMEM_LEN);
837 exit_release_wbase:
838 	release_region(data->wbase, WAKEUP_IOMEM_LEN);
839 exit_free_data:
840 	kfree(data);
841 	pnp_set_drvdata(device, NULL);
842 exit:
843 	return err;
844 }
845 
846 static void __devexit
847 wbcir_remove(struct pnp_dev *device)
848 {
849 	struct wbcir_data *data = pnp_get_drvdata(device);
850 
851 	/* Disable interrupts */
852 	wbcir_select_bank(data, WBCIR_BANK_0);
853 	outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER);
854 
855 	free_irq(data->irq, device);
856 
857 	/* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */
858 	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17);
859 
860 	/* Clear CEIR_EN */
861 	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01);
862 
863 	/* Clear BUFF_EN, END_EN, MATCH_EN */
864 	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
865 
866 	rc_unregister_device(data->dev);
867 
868 	led_trigger_unregister_simple(data->rxtrigger);
869 	led_trigger_unregister_simple(data->txtrigger);
870 	led_classdev_unregister(&data->led);
871 
872 	/* This is ok since &data->led isn't actually used */
873 	wbcir_led_brightness_set(&data->led, LED_OFF);
874 
875 	release_region(data->wbase, WAKEUP_IOMEM_LEN);
876 	release_region(data->ebase, EHFUNC_IOMEM_LEN);
877 	release_region(data->sbase, SP_IOMEM_LEN);
878 
879 	kfree(data);
880 
881 	pnp_set_drvdata(device, NULL);
882 }
883 
884 static const struct pnp_device_id wbcir_ids[] = {
885 	{ "WEC1022", 0 },
886 	{ "", 0 }
887 };
888 MODULE_DEVICE_TABLE(pnp, wbcir_ids);
889 
890 static struct pnp_driver wbcir_driver = {
891 	.name     = WBCIR_NAME,
892 	.id_table = wbcir_ids,
893 	.probe    = wbcir_probe,
894 	.remove   = __devexit_p(wbcir_remove),
895 	.suspend  = wbcir_suspend,
896 	.resume   = wbcir_resume,
897 	.shutdown = wbcir_shutdown
898 };
899 
900 static int __init
901 wbcir_init(void)
902 {
903 	int ret;
904 
905 	switch (protocol) {
906 	case IR_PROTOCOL_RC5:
907 	case IR_PROTOCOL_NEC:
908 	case IR_PROTOCOL_RC6:
909 		break;
910 	default:
911 		printk(KERN_ERR DRVNAME ": Invalid power-on protocol\n");
912 	}
913 
914 	ret = pnp_register_driver(&wbcir_driver);
915 	if (ret)
916 		printk(KERN_ERR DRVNAME ": Unable to register driver\n");
917 
918 	return ret;
919 }
920 
921 static void __exit
922 wbcir_exit(void)
923 {
924 	pnp_unregister_driver(&wbcir_driver);
925 }
926 
927 module_init(wbcir_init);
928 module_exit(wbcir_exit);
929 
930 MODULE_AUTHOR("David H�rdeman <david@hardeman.nu>");
931 MODULE_DESCRIPTION("Winbond SuperI/O Consumer IR Driver");
932 MODULE_LICENSE("GPL");
933