[media] ir-core: make struct rc_dev the primary interface
[pandora-kernel.git] / drivers / media / rc / winbond-cir.c
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/ir-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");