2 * winbond-cir.c - Driver for the Consumer IR functionality of Winbond
5 * Currently supports the Winbond WPCD376i chip (PNP id WEC1022), but
6 * could probably support others (Winbond WEC102X, NatSemi, etc)
7 * with minor modifications.
9 * Original Author: David Härdeman <david@hardeman.nu>
10 * Copyright (C) 2009 - 2010 David Härdeman <david@hardeman.nu>
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
17 * o Winbond WPCD376I datasheet helpfully provided by Jesse Barnes at Intel
18 * o NatSemi PC87338/PC97338 datasheet (for the serial port stuff)
22 * o Wake-On-CIR functionality
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.
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.
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.
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>
51 #include <linux/bitrev.h>
52 #include <linux/slab.h>
53 #include <media/rc-core.h>
55 #define DRVNAME "winbond-cir"
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 */
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 */
76 /* SP3 Banked Registers, relative to data->sbase */
77 #define WBCIR_REG_SP3_BSR 0x03 /* Bank Select, all banks */
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 */
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 */
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 */
100 #define WBCIR_REG_SP3_IRCR1 0x02 /* Infrared Control 1 */
102 #define WBCIR_REG_SP3_IRCR2 0x04 /* Infrared Control 2 */
104 #define WBCIR_REG_SP3_IRCR3 0x00 /* Infrared Control 3 */
105 #define WBCIR_REG_SP3_SIR_PW 0x02 /* SIR Pulse Width */
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 */
114 * Magic values follow
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
138 /* Valid banks for the SP3 UART */
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,
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 */
166 /* Per-device data */
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 */
177 struct led_trigger
*rxtrigger
;
178 struct led_trigger
*txtrigger
;
179 struct led_classdev led
;
181 /* RX irdata state */
184 struct ir_raw_event ev
;
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)");
192 static int invert
; /* default = 0 */
193 module_param(invert
, bool, 0444);
194 MODULE_PARM_DESC(invert
, "Invert the signal from the IR receiver");
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");
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)");
207 /*****************************************************************************
211 *****************************************************************************/
213 /* Caller needs to hold wbcir_lock */
215 wbcir_set_bits(unsigned long addr
, u8 bits
, u8 mask
)
220 val
= ((val
& ~mask
) | (bits
& mask
));
224 /* Selects the register bank for the serial port */
226 wbcir_select_bank(struct wbcir_data
*data
, enum wbcir_bank bank
)
228 outb(bank
, data
->sbase
+ WBCIR_REG_SP3_BSR
);
231 static enum led_brightness
232 wbcir_led_brightness_get(struct led_classdev
*led_cdev
)
234 struct wbcir_data
*data
= container_of(led_cdev
,
238 if (inb(data
->ebase
+ WBCIR_REG_ECEIR_CTS
) & WBCIR_LED_ENABLE
)
245 wbcir_led_brightness_set(struct led_classdev
*led_cdev
,
246 enum led_brightness brightness
)
248 struct wbcir_data
*data
= container_of(led_cdev
,
252 wbcir_set_bits(data
->ebase
+ WBCIR_REG_ECEIR_CTS
,
253 brightness
== LED_OFF
? 0x00 : WBCIR_LED_ENABLE
,
257 /* Manchester encodes bits to RC6 message cells (see wbcir_shutdown) */
259 wbcir_to_rc6cells(u8 val
)
265 for (i
= 0; i
< 4; i
++) {
267 coded
|= 0x02 << (i
* 2);
269 coded
|= 0x01 << (i
* 2);
276 /*****************************************************************************
278 * INTERRUPT FUNCTIONS
280 *****************************************************************************/
283 wbcir_irq_handler(int irqno
, void *cookie
)
285 struct pnp_dev
*device
= cookie
;
286 struct wbcir_data
*data
= pnp_get_drvdata(device
);
293 spin_lock_irqsave(&data
->spinlock
, flags
);
295 wbcir_select_bank(data
, WBCIR_BANK_0
);
297 status
= inb(data
->sbase
+ WBCIR_REG_SP3_EIR
);
299 if (!(status
& (WBCIR_IRQ_RX
| WBCIR_IRQ_ERR
))) {
300 spin_unlock_irqrestore(&data
->spinlock
, flags
);
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
);
310 if (!(status
& WBCIR_IRQ_RX
))
313 if (!data
->irdata_active
) {
314 data
->irdata_active
= true;
315 led_trigger_event(data
->rxtrigger
, LED_FULL
);
318 /* Since RXHDLEV is set, at least 8 bytes are in the FIFO */
319 insb(data
->sbase
+ WBCIR_REG_SP3_RXDATA
, &irdata
[0], 8);
321 for (i
= 0; i
< 8; i
++) {
325 if (irdata
[i
] != 0xFF && irdata
[i
] != 0x00)
328 if (data
->irdata_error
)
331 pulse
= irdata
[i
] & 0x80 ? false : true;
332 duration
= (irdata
[i
] & 0x7F) * 10000; /* ns */
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;
340 data
->ev
.pulse
= pulse
;
343 data
->ev
.duration
+= duration
;
347 if (data
->ev
.duration
!= 0 && !data
->irdata_error
) {
348 ir_raw_event_store(data
->dev
, &data
->ev
);
349 data
->ev
.duration
= 0;
353 outb(WBCIR_RX_DISABLE
, data
->sbase
+ WBCIR_REG_SP3_ASCR
);
356 while (inb(data
->sbase
+ WBCIR_REG_SP3_LSR
) & WBCIR_RX_AVAIL
)
357 inb(data
->sbase
+ WBCIR_REG_SP3_RXDATA
);
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
);
365 ir_raw_event_handle(data
->dev
);
368 spin_unlock_irqrestore(&data
->spinlock
, flags
);
374 /*****************************************************************************
376 * SETUP/INIT/SUSPEND/RESUME FUNCTIONS
378 *****************************************************************************/
381 wbcir_shutdown(struct pnp_dev
*device
)
383 struct device
*dev
= &device
->dev
;
384 struct wbcir_data
*data
= pnp_get_drvdata(device
);
391 memset(match
, 0, sizeof(match
));
392 memset(mask
, 0, sizeof(mask
));
394 if (wake_sc
== INVALID_SCANCODE
|| !device_may_wakeup(dev
)) {
400 case IR_PROTOCOL_RC5
:
401 if (wake_sc
> 0xFFF) {
403 dev_err(dev
, "RC5 - Invalid wake scancode\n");
407 /* Mask = 13 bits, ex toggle */
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 */
419 case IR_PROTOCOL_NEC
:
420 if (wake_sc
> 0xFFFFFF) {
422 dev_err(dev
, "NEC - Invalid wake scancode\n");
426 mask
[0] = mask
[1] = mask
[2] = mask
[3] = 0xFF;
428 match
[1] = bitrev8((wake_sc
& 0xFF));
429 match
[0] = ~match
[1];
431 match
[3] = bitrev8((wake_sc
& 0xFF00) >> 8);
432 if (wake_sc
> 0xFFFF)
433 match
[2] = bitrev8((wake_sc
& 0xFF0000) >> 16);
435 match
[2] = ~match
[3];
439 case IR_PROTOCOL_RC6
:
441 if (wake_rc6mode
== 0) {
442 if (wake_sc
> 0xFFFF) {
444 dev_err(dev
, "RC6 - Invalid wake scancode\n");
449 match
[0] = wbcir_to_rc6cells(wake_sc
>> 0);
451 match
[1] = wbcir_to_rc6cells(wake_sc
>> 4);
455 match
[2] = wbcir_to_rc6cells(wake_sc
>> 8);
457 match
[3] = wbcir_to_rc6cells(wake_sc
>> 12);
461 match
[4] = 0x50; /* mode1 = mode0 = 0, ignore toggle */
463 match
[5] = 0x09; /* start bit = 1, mode2 = 0 */
468 } else if (wake_rc6mode
== 6) {
472 match
[i
] = wbcir_to_rc6cells(wake_sc
>> 0);
474 match
[i
] = wbcir_to_rc6cells(wake_sc
>> 4);
477 /* Address + Toggle */
478 match
[i
] = wbcir_to_rc6cells(wake_sc
>> 8);
480 match
[i
] = wbcir_to_rc6cells(wake_sc
>> 12);
483 /* Customer bits 7 - 0 */
484 match
[i
] = wbcir_to_rc6cells(wake_sc
>> 16);
486 match
[i
] = wbcir_to_rc6cells(wake_sc
>> 20);
489 if (wake_sc
& 0x80000000) {
490 /* Customer range bit and bits 15 - 8 */
491 match
[i
] = wbcir_to_rc6cells(wake_sc
>> 24);
493 match
[i
] = wbcir_to_rc6cells(wake_sc
>> 28);
496 } else if (wake_sc
<= 0x007FFFFF) {
500 dev_err(dev
, "RC6 - Invalid wake scancode\n");
505 match
[i
] = 0x93; /* mode1 = mode0 = 1, submode = 0 */
507 match
[i
] = 0x0A; /* start bit = 1, mode2 = 1 */
512 dev_err(dev
, "RC6 - Invalid wake mode\n");
524 /* Set compare and compare mask */
525 wbcir_set_bits(data
->wbase
+ WBCIR_REG_WCEIR_INDEX
,
526 WBCIR_REGSEL_COMPARE
| WBCIR_REG_ADDR0
,
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
,
532 outsb(data
->wbase
+ WBCIR_REG_WCEIR_DATA
, mask
, 11);
534 /* RC6 Compare String Len */
535 outb(rc6_csl
, data
->wbase
+ WBCIR_REG_WCEIR_CSL
);
537 /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */
538 wbcir_set_bits(data
->wbase
+ WBCIR_REG_WCEIR_STS
, 0x17, 0x17);
540 /* Clear BUFF_EN, Clear END_EN, Set MATCH_EN */
541 wbcir_set_bits(data
->wbase
+ WBCIR_REG_WCEIR_EV_EN
, 0x01, 0x07);
544 wbcir_set_bits(data
->wbase
+ WBCIR_REG_WCEIR_CTL
, 0x01, 0x01);
547 /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */
548 wbcir_set_bits(data
->wbase
+ WBCIR_REG_WCEIR_EV_EN
, 0x00, 0x07);
551 wbcir_set_bits(data
->wbase
+ WBCIR_REG_WCEIR_CTL
, 0x00, 0x01);
554 /* Disable interrupts */
555 wbcir_select_bank(data
, WBCIR_BANK_0
);
556 outb(WBCIR_IRQ_NONE
, data
->sbase
+ WBCIR_REG_SP3_IER
);
559 data
->irdata_active
= false;
560 led_trigger_event(data
->rxtrigger
, LED_OFF
);
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
568 disable_irq(data
->irq
);
572 wbcir_suspend(struct pnp_dev
*device
, pm_message_t state
)
574 wbcir_shutdown(device
);
579 wbcir_init_hw(struct wbcir_data
*data
)
583 /* Disable interrupts */
584 wbcir_select_bank(data
, WBCIR_BANK_0
);
585 outb(WBCIR_IRQ_NONE
, data
->sbase
+ WBCIR_REG_SP3_IER
);
587 /* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */
591 outb(tmp
, data
->wbase
+ WBCIR_REG_WCEIR_CTL
);
593 /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */
594 wbcir_set_bits(data
->wbase
+ WBCIR_REG_WCEIR_STS
, 0x17, 0x17);
596 /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */
597 wbcir_set_bits(data
->wbase
+ WBCIR_REG_WCEIR_EV_EN
, 0x00, 0x07);
599 /* Set RC5 cell time to correspond to 36 kHz */
600 wbcir_set_bits(data
->wbase
+ WBCIR_REG_WCEIR_CFG1
, 0x4A, 0x7F);
604 outb(0x04, data
->ebase
+ WBCIR_REG_ECEIR_CCTL
);
606 outb(0x00, data
->ebase
+ WBCIR_REG_ECEIR_CCTL
);
609 * Clear IR LED, set SP3 clock to 24Mhz
610 * set SP3_IRRX_SW to binary 01, helpfully not documented
612 outb(0x10, data
->ebase
+ WBCIR_REG_ECEIR_CTS
);
614 /* Enable extended mode */
615 wbcir_select_bank(data
, WBCIR_BANK_2
);
616 outb(WBCIR_EXT_ENABLE
, data
->sbase
+ WBCIR_REG_SP3_EXCR1
);
619 * Configure baud generator, IR data will be sampled at
620 * a bitrate of: (24Mhz * prescaler) / (divisor * 16).
622 * The ECIR registers include a flag to change the
623 * 24Mhz clock freq to 48Mhz.
625 * It's not documented in the specs, but fifo levels
626 * other than 16 seems to be unsupported.
629 /* prescaler 1.0, tx/rx fifo lvl 16 */
630 outb(0x30, data
->sbase
+ WBCIR_REG_SP3_EXCR2
);
632 /* Set baud divisor to generate one byte per bit/cell */
634 case IR_PROTOCOL_RC5
:
635 outb(0xA7, data
->sbase
+ WBCIR_REG_SP3_BGDL
);
637 case IR_PROTOCOL_RC6
:
638 outb(0x53, data
->sbase
+ WBCIR_REG_SP3_BGDL
);
640 case IR_PROTOCOL_NEC
:
641 outb(0x69, data
->sbase
+ WBCIR_REG_SP3_BGDL
);
644 outb(0x00, data
->sbase
+ WBCIR_REG_SP3_BGDH
);
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 */
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
);
657 wbcir_select_bank(data
, WBCIR_BANK_4
);
658 outb(0x00, data
->sbase
+ WBCIR_REG_SP3_IRCR1
);
660 /* Enable MSR interrupt, Clear AUX_IRX */
661 wbcir_select_bank(data
, WBCIR_BANK_5
);
662 outb(0x00, data
->sbase
+ WBCIR_REG_SP3_IRCR2
);
665 wbcir_select_bank(data
, WBCIR_BANK_6
);
666 outb(0x20, data
->sbase
+ WBCIR_REG_SP3_IRCR3
);
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
);
673 /* Set invert and pin direction */
675 outb(0x10, data
->sbase
+ WBCIR_REG_SP3_IRCFG4
);
677 outb(0x00, data
->sbase
+ WBCIR_REG_SP3_IRCFG4
);
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
);
683 /* Clear AUX status bits */
684 outb(0xE0, data
->sbase
+ WBCIR_REG_SP3_ASCR
);
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
);
694 /* Enable interrupts */
695 outb(WBCIR_IRQ_RX
| WBCIR_IRQ_ERR
, data
->sbase
+ WBCIR_REG_SP3_IER
);
699 wbcir_resume(struct pnp_dev
*device
)
701 struct wbcir_data
*data
= pnp_get_drvdata(device
);
704 enable_irq(data
->irq
);
710 wbcir_probe(struct pnp_dev
*device
, const struct pnp_device_id
*dev_id
)
712 struct device
*dev
= &device
->dev
;
713 struct wbcir_data
*data
;
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");
723 data
= kzalloc(sizeof(*data
), GFP_KERNEL
);
729 pnp_set_drvdata(device
, data
);
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);
737 if (data
->wbase
== 0 || data
->ebase
== 0 ||
738 data
->sbase
== 0 || data
->irq
== 0) {
740 dev_err(dev
, "Invalid resources\n");
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
);
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);
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);
759 goto exit_release_wbase
;
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);
766 goto exit_release_ebase
;
769 err
= request_irq(data
->irq
, wbcir_irq_handler
,
770 IRQF_DISABLED
, DRVNAME
, device
);
772 dev_err(dev
, "Failed to claim IRQ %u\n", data
->irq
);
774 goto exit_release_sbase
;
777 led_trigger_register_simple("cir-tx", &data
->txtrigger
);
778 if (!data
->txtrigger
) {
783 led_trigger_register_simple("cir-rx", &data
->rxtrigger
);
784 if (!data
->rxtrigger
) {
786 goto exit_unregister_txtrigger
;
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
);
795 goto exit_unregister_rxtrigger
;
797 data
->dev
= rc_allocate_device();
800 goto exit_unregister_led
;
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
;
813 err
= rc_register_device(data
->dev
);
817 device_init_wakeup(&device
->dev
, 1);
824 rc_free_device(data
->dev
);
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
);
832 free_irq(data
->irq
, device
);
834 release_region(data
->sbase
, SP_IOMEM_LEN
);
836 release_region(data
->ebase
, EHFUNC_IOMEM_LEN
);
838 release_region(data
->wbase
, WAKEUP_IOMEM_LEN
);
841 pnp_set_drvdata(device
, NULL
);
846 static void __devexit
847 wbcir_remove(struct pnp_dev
*device
)
849 struct wbcir_data
*data
= pnp_get_drvdata(device
);
851 /* Disable interrupts */
852 wbcir_select_bank(data
, WBCIR_BANK_0
);
853 outb(WBCIR_IRQ_NONE
, data
->sbase
+ WBCIR_REG_SP3_IER
);
855 free_irq(data
->irq
, device
);
857 /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */
858 wbcir_set_bits(data
->wbase
+ WBCIR_REG_WCEIR_STS
, 0x17, 0x17);
861 wbcir_set_bits(data
->wbase
+ WBCIR_REG_WCEIR_CTL
, 0x00, 0x01);
863 /* Clear BUFF_EN, END_EN, MATCH_EN */
864 wbcir_set_bits(data
->wbase
+ WBCIR_REG_WCEIR_EV_EN
, 0x00, 0x07);
866 rc_unregister_device(data
->dev
);
868 led_trigger_unregister_simple(data
->rxtrigger
);
869 led_trigger_unregister_simple(data
->txtrigger
);
870 led_classdev_unregister(&data
->led
);
872 /* This is ok since &data->led isn't actually used */
873 wbcir_led_brightness_set(&data
->led
, LED_OFF
);
875 release_region(data
->wbase
, WAKEUP_IOMEM_LEN
);
876 release_region(data
->ebase
, EHFUNC_IOMEM_LEN
);
877 release_region(data
->sbase
, SP_IOMEM_LEN
);
881 pnp_set_drvdata(device
, NULL
);
884 static const struct pnp_device_id wbcir_ids
[] = {
888 MODULE_DEVICE_TABLE(pnp
, wbcir_ids
);
890 static struct pnp_driver wbcir_driver
= {
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
906 case IR_PROTOCOL_RC5
:
907 case IR_PROTOCOL_NEC
:
908 case IR_PROTOCOL_RC6
:
911 printk(KERN_ERR DRVNAME
": Invalid power-on protocol\n");
914 ret
= pnp_register_driver(&wbcir_driver
);
916 printk(KERN_ERR DRVNAME
": Unable to register driver\n");
924 pnp_unregister_driver(&wbcir_driver
);
927 module_init(wbcir_init
);
928 module_exit(wbcir_exit
);
930 MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
931 MODULE_DESCRIPTION("Winbond SuperI/O Consumer IR Driver");
932 MODULE_LICENSE("GPL");