]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/input/misc/winbond-cir.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[karo-tx-linux.git] / drivers / input / misc / winbond-cir.c
index c8f5a9a3fa140d73218c7e4ce6a162da8287500f..64f1de7960c699845337ad1080c9deb78598f12a 100644 (file)
@@ -56,6 +56,7 @@
 #include <linux/io.h>
 #include <linux/bitrev.h>
 #include <linux/bitops.h>
+#include <linux/slab.h>
 
 #define DRVNAME "winbond-cir"
 
@@ -385,26 +386,24 @@ wbcir_do_getkeycode(struct wbcir_data *data, u32 scancode)
 }
 
 static int
-wbcir_getkeycode(struct input_dev *dev, int scancode, int *keycode)
+wbcir_getkeycode(struct input_dev *dev,
+                unsigned int scancode, unsigned int *keycode)
 {
        struct wbcir_data *data = input_get_drvdata(dev);
 
-       *keycode = (int)wbcir_do_getkeycode(data, (u32)scancode);
+       *keycode = wbcir_do_getkeycode(data, scancode);
        return 0;
 }
 
 static int
-wbcir_setkeycode(struct input_dev *dev, int sscancode, int keycode)
+wbcir_setkeycode(struct input_dev *dev,
+                unsigned int scancode, unsigned int keycode)
 {
        struct wbcir_data *data = input_get_drvdata(dev);
        struct wbcir_keyentry *keyentry;
        struct wbcir_keyentry *new_keyentry;
        unsigned long flags;
        unsigned int old_keycode = KEY_RESERVED;
-       u32 scancode = (u32)sscancode;
-
-       if (keycode < 0 || keycode > KEY_MAX)
-               return -EINVAL;
 
        new_keyentry = kmalloc(sizeof(*new_keyentry), GFP_KERNEL);
        if (!new_keyentry)
@@ -538,6 +537,7 @@ wbcir_reset_irdata(struct wbcir_data *data)
        data->irdata_count = 0;
        data->irdata_off = 0;
        data->irdata_error = 0;
+       data->idle_count = 0;
 }
 
 /* Adds one bit of irdata */
@@ -1006,7 +1006,6 @@ wbcir_irq_handler(int irqno, void *cookie)
                }
 
                wbcir_reset_irdata(data);
-               data->idle_count = 0;
        }
 
 out:
@@ -1018,7 +1017,7 @@ out:
 
 /*****************************************************************************
  *
- * SUSPEND/RESUME FUNCTIONS
+ * SETUP/INIT/SUSPEND/RESUME FUNCTIONS
  *
  *****************************************************************************/
 
@@ -1197,7 +1196,16 @@ finish:
        }
 
        /* Disable interrupts */
+       wbcir_select_bank(data, WBCIR_BANK_0);
        outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER);
+
+       /*
+        * ACPI will set the HW disable bit for SP3 which means that the
+        * output signals are left in an undefined state which may cause
+        * spurious interrupts which we need to ignore until the hardware
+        * is reinitialized.
+        */
+       disable_irq(data->irq);
 }
 
 static int
@@ -1207,37 +1215,15 @@ wbcir_suspend(struct pnp_dev *device, pm_message_t state)
        return 0;
 }
 
-static int
-wbcir_resume(struct pnp_dev *device)
-{
-       struct wbcir_data *data = pnp_get_drvdata(device);
-
-       /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */
-       wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
-
-       /* Clear CEIR_EN */
-       wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01);
-
-       /* Enable interrupts */
-       wbcir_reset_irdata(data);
-       outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER);
-
-       return 0;
-}
-
-
-
-/*****************************************************************************
- *
- * SETUP/INIT FUNCTIONS
- *
- *****************************************************************************/
-
 static void
-wbcir_cfg_ceir(struct wbcir_data *data)
+wbcir_init_hw(struct wbcir_data *data)
 {
        u8 tmp;
 
+       /* Disable interrupts */
+       wbcir_select_bank(data, WBCIR_BANK_0);
+       outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER);
+
        /* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */
        tmp = protocol << 4;
        if (invert)
@@ -1264,6 +1250,93 @@ wbcir_cfg_ceir(struct wbcir_data *data)
         * set SP3_IRRX_SW to binary 01, helpfully not documented
         */
        outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS);
+
+       /* Enable extended mode */
+       wbcir_select_bank(data, WBCIR_BANK_2);
+       outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1);
+
+       /*
+        * Configure baud generator, IR data will be sampled at
+        * a bitrate of: (24Mhz * prescaler) / (divisor * 16).
+        *
+        * The ECIR registers include a flag to change the
+        * 24Mhz clock freq to 48Mhz.
+        *
+        * It's not documented in the specs, but fifo levels
+        * other than 16 seems to be unsupported.
+        */
+
+       /* prescaler 1.0, tx/rx fifo lvl 16 */
+       outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2);
+
+       /* Set baud divisor to generate one byte per bit/cell */
+       switch (protocol) {
+       case IR_PROTOCOL_RC5:
+               outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL);
+               break;
+       case IR_PROTOCOL_RC6:
+               outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL);
+               break;
+       case IR_PROTOCOL_NEC:
+               outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL);
+               break;
+       }
+       outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH);
+
+       /* Set CEIR mode */
+       wbcir_select_bank(data, WBCIR_BANK_0);
+       outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR);
+       inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */
+       inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */
+
+       /* Disable RX demod, run-length encoding/decoding, set freq span */
+       wbcir_select_bank(data, WBCIR_BANK_7);
+       outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG);
+
+       /* Disable timer */
+       wbcir_select_bank(data, WBCIR_BANK_4);
+       outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1);
+
+       /* Enable MSR interrupt, Clear AUX_IRX */
+       wbcir_select_bank(data, WBCIR_BANK_5);
+       outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2);
+
+       /* Disable CRC */
+       wbcir_select_bank(data, WBCIR_BANK_6);
+       outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3);
+
+       /* Set RX/TX (de)modulation freq, not really used */
+       wbcir_select_bank(data, WBCIR_BANK_7);
+       outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC);
+       outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC);
+
+       /* Set invert and pin direction */
+       if (invert)
+               outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4);
+       else
+               outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4);
+
+       /* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */
+       wbcir_select_bank(data, WBCIR_BANK_0);
+       outb(0x97, data->sbase + WBCIR_REG_SP3_FCR);
+
+       /* Clear AUX status bits */
+       outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR);
+
+       /* Enable interrupts */
+       wbcir_reset_irdata(data);
+       outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER);
+}
+
+static int
+wbcir_resume(struct pnp_dev *device)
+{
+       struct wbcir_data *data = pnp_get_drvdata(device);
+
+       wbcir_init_hw(data);
+       enable_irq(data->irq);
+
+       return 0;
 }
 
 static int __devinit
@@ -1393,86 +1466,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
 
        device_init_wakeup(&device->dev, 1);
 
-       wbcir_cfg_ceir(data);
-
-       /* Disable interrupts */
-       wbcir_select_bank(data, WBCIR_BANK_0);
-       outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER);
-
-       /* Enable extended mode */
-       wbcir_select_bank(data, WBCIR_BANK_2);
-       outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1);
-
-       /*
-        * Configure baud generator, IR data will be sampled at
-        * a bitrate of: (24Mhz * prescaler) / (divisor * 16).
-        *
-        * The ECIR registers include a flag to change the
-        * 24Mhz clock freq to 48Mhz.
-        *
-        * It's not documented in the specs, but fifo levels
-        * other than 16 seems to be unsupported.
-        */
-
-       /* prescaler 1.0, tx/rx fifo lvl 16 */
-       outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2);
-
-       /* Set baud divisor to generate one byte per bit/cell */
-       switch (protocol) {
-       case IR_PROTOCOL_RC5:
-               outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL);
-               break;
-       case IR_PROTOCOL_RC6:
-               outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL);
-               break;
-       case IR_PROTOCOL_NEC:
-               outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL);
-               break;
-       }
-       outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH);
-
-       /* Set CEIR mode */
-       wbcir_select_bank(data, WBCIR_BANK_0);
-       outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR);
-       inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */
-       inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */
-
-       /* Disable RX demod, run-length encoding/decoding, set freq span */
-       wbcir_select_bank(data, WBCIR_BANK_7);
-       outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG);
-
-       /* Disable timer */
-       wbcir_select_bank(data, WBCIR_BANK_4);
-       outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1);
-
-       /* Enable MSR interrupt, Clear AUX_IRX */
-       wbcir_select_bank(data, WBCIR_BANK_5);
-       outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2);
-
-       /* Disable CRC */
-       wbcir_select_bank(data, WBCIR_BANK_6);
-       outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3);
-
-       /* Set RX/TX (de)modulation freq, not really used */
-       wbcir_select_bank(data, WBCIR_BANK_7);
-       outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC);
-       outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC);
-
-       /* Set invert and pin direction */
-       if (invert)
-               outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4);
-       else
-               outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4);
-
-       /* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */
-       wbcir_select_bank(data, WBCIR_BANK_0);
-       outb(0x97, data->sbase + WBCIR_REG_SP3_FCR);
-
-       /* Clear AUX status bits */
-       outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR);
-
-       /* Enable interrupts */
-       outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER);
+       wbcir_init_hw(data);
 
        return 0;