The patch titled add-a-driver-for-the-winbond-wpcd376i-ir-functionality-update has been added to the -mm tree. Its filename is add-a-driver-for-the-winbond-wpcd376i-ir-functionality-update.patch Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/SubmitChecklist when testing your code *** See http://userweb.kernel.org/~akpm/stuff/added-to-mm.txt to find out what to do about this The current -mm tree may be found at http://userweb.kernel.org/~akpm/mmotm/ ------------------------------------------------------ Subject: add-a-driver-for-the-winbond-wpcd376i-ir-functionality-update From: David Härdeman <david@xxxxxxxxxxx> Changes since the second post to the list (AKPM's remarks): o Various comments added o Removed some casts o use bitrev8 o convert data->irdata to unsigned longs, use __set_bit and test_bit Signed-off-by: David Härdeman <david@xxxxxxxxxxx> Cc: Jesse Barnes <jbarnes@xxxxxxxxxxxxxxxx> Cc: Bjorn Helgaas <bjorn.helgaas@xxxxxx> Cc: Len Brown <lenb@xxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- MAINTAINERS | 2 drivers/input/misc/Kconfig | 30 +++++----- drivers/input/misc/Makefile | 2 drivers/input/misc/winbond-cir.c | 81 ++++++++++++++--------------- 4 files changed, 58 insertions(+), 57 deletions(-) diff -puN MAINTAINERS~add-a-driver-for-the-winbond-wpcd376i-ir-functionality-update MAINTAINERS --- a/MAINTAINERS~add-a-driver-for-the-winbond-wpcd376i-ir-functionality-update +++ a/MAINTAINERS @@ -6457,7 +6457,7 @@ S: Maintained F: drivers/scsi/wd7000.c WINBOND CIR DRIVER -P: David Härdeman +P: David Härdeman M: david@xxxxxxxxxxx S: Maintained F: drivers/input/misc/winbond-cir.c diff -puN drivers/input/misc/Kconfig~add-a-driver-for-the-winbond-wpcd376i-ir-functionality-update drivers/input/misc/Kconfig --- a/drivers/input/misc/Kconfig~add-a-driver-for-the-winbond-wpcd376i-ir-functionality-update +++ a/drivers/input/misc/Kconfig @@ -222,6 +222,21 @@ config INPUT_SGI_BTNS To compile this driver as a module, choose M here: the module will be called sgi_btns. +config INPUT_WINBOND_CIR + tristate "Winbond IR remote control" + depends on X86 && ACPI + select LEDS_CLASS + help + Say Y here if you want to use the IR remote functionality found + in some Winbond SuperI/O chips. Currently only the WPCD376I + chip is supported (included in some Intel Media series motherboards). + + IR Receive and wake-on-IR from suspend and power-off is currently + supported. + + To compile this driver as a module, choose M here: the module will be + called winbond_cir. + config HP_SDC_RTC tristate "HP SDC Real Time Clock" depends on (GSC || HP300) && SERIO @@ -269,19 +284,4 @@ config INPUT_DM355EVM To compile this driver as a module, choose M here: the module will be called dm355evm_keys. - -config INPUT_WINBOND_CIR - tristate "Winbond IR remote control" - depends on X86 && ACPI - select LEDS_CLASS - help - Say Y here if you want to use the IR remote functionality found - in some Winbond SuperI/O chips. Currently only the WPCD376I - chip is supported (included in some Intel Media series motherboards). - - IR Receive and wake-on-IR from suspend and power-off is currently - supported. - - To compile this driver as a module, choose M here: the module will be - called winbond_cir. endif diff -puN drivers/input/misc/Makefile~add-a-driver-for-the-winbond-wpcd376i-ir-functionality-update drivers/input/misc/Makefile --- a/drivers/input/misc/Makefile~add-a-driver-for-the-winbond-wpcd376i-ir-functionality-update +++ a/drivers/input/misc/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf5 obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o obj-$(CONFIG_INPUT_POWERMATE) += powermate.o obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o +obj-$(CONFIG_INPUT_WINBOND_CIR) += winbond-cir.o obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o @@ -26,4 +27,3 @@ obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += obj-$(CONFIG_INPUT_UINPUT) += uinput.o obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o obj-$(CONFIG_INPUT_YEALINK) += yealink.o -obj-$(CONFIG_INPUT_WINBOND_CIR) += winbond-cir.o diff -puN drivers/input/misc/winbond-cir.c~add-a-driver-for-the-winbond-wpcd376i-ir-functionality-update drivers/input/misc/winbond-cir.c --- a/drivers/input/misc/winbond-cir.c~add-a-driver-for-the-winbond-wpcd376i-ir-functionality-update +++ a/drivers/input/misc/winbond-cir.c @@ -6,8 +6,8 @@ * could probably support others (Winbond WEC102X, NatSemi, etc) * with minor modifications. * - * Original Author: David Härdeman <david@xxxxxxxxxxx> - * Copyright (C) 2009 David Härdeman <david@xxxxxxxxxxx> + * Original Author: David Härdeman <david@xxxxxxxxxxx> + * Copyright (C) 2009 David Härdeman <david@xxxxxxxxxxx> * * Dedicated to Matilda, my newborn daughter, without whose loving attention * this driver would have been finished in half the time and with a fraction @@ -54,6 +54,8 @@ #include <linux/spinlock.h> #include <linux/pci_ids.h> #include <linux/io.h> +#include <linux/bitrev.h> +#include <linux/bitops.h> #define DRVNAME "winbond-cir" @@ -114,7 +116,7 @@ #define WBCIR_REG_SP3_IRCFG4 0x07 /* Infrared Config 4 */ /* - * Magic values follows + * Magic values follow */ /* No interrupts for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ @@ -235,6 +237,7 @@ static struct wbcir_key rc6_def_keymap[] { 0x800F0417, KEY_RECORD }, }; +/* Registers and other state is protected by wbcir_lock */ struct wbcir_data { unsigned long wbase; /* Wake-Up Baseaddr */ unsigned long ebase; /* Enhanced Func. Baseaddr */ @@ -247,7 +250,6 @@ struct wbcir_data { struct led_trigger *txtrigger; struct led_classdev led; - /* The rest is protected by wbcir_lock */ u32 last_scancode; unsigned int last_keycode; u8 last_toggle; @@ -256,7 +258,7 @@ struct wbcir_data { unsigned int idle_count; /* RX irdata and parsing state */ - u8 irdata[30]; + unsigned long irdata[30]; unsigned int irdata_count; unsigned int irdata_idle; unsigned int irdata_off; @@ -292,6 +294,7 @@ MODULE_PARM_DESC(wake_rc6mode, "RC6 mode * *****************************************************************************/ +/* Caller needs to hold wbcir_lock */ static void wbcir_set_bits(unsigned long addr, u8 bits, u8 mask) { @@ -302,6 +305,7 @@ wbcir_set_bits(unsigned long addr, u8 bi outb(val, addr); } +/* Selects the register bank for the serial port */ static inline void wbcir_select_bank(struct wbcir_data *data, enum wbcir_bank bank) { @@ -334,14 +338,7 @@ wbcir_led_brightness_set(struct led_clas WBCIR_LED_ENABLE); } -static u8 -wbcir_revbyte(u8 byte) -{ - byte = ((byte >> 1) & 0x55) | ((byte << 1) & 0xAA); - byte = ((byte >> 2) & 0x33) | ((byte << 2) & 0xCC); - return (byte >> 4) | (byte<<4); -} - +/* Manchester encodes bits to RC6 message cells (see wbcir_parse_rc6) */ static u8 wbcir_to_rc6cells(u8 val) { @@ -389,16 +386,11 @@ wbcir_do_getkeycode(struct wbcir_data *d } static int -wbcir_getkeycode(struct input_dev *dev, int sscancode, int *keycode) +wbcir_getkeycode(struct input_dev *dev, int scancode, int *keycode) { - unsigned int scancode = (unsigned int)sscancode; struct wbcir_data *data = input_get_drvdata(dev); - if (scancode < 0 || scancode > 0xFFFFFFFF) - return -EINVAL; - *keycode = (int)wbcir_do_getkeycode(data, (u32)scancode); - return 0; } @@ -410,10 +402,7 @@ wbcir_setkeycode(struct input_dev *dev, struct wbcir_keyentry *new_keyentry; unsigned long flags; unsigned int old_keycode = KEY_RESERVED; - unsigned int scancode = (unsigned int)sscancode; - - if (scancode < 0 || scancode > 0xFFFFFFFF) - return -EINVAL; + u32 scancode = (u32)sscancode; if (keycode < 0 || keycode > KEY_MAX) return -EINVAL; @@ -442,8 +431,8 @@ wbcir_setkeycode(struct input_dev *dev, set_bit(keycode, dev->keybit); if (old_keycode == KEY_RESERVED) { - new_keyentry->key.scancode = (u32)scancode; - new_keyentry->key.keycode = (unsigned int)keycode; + new_keyentry->key.scancode = scancode; + new_keyentry->key.keycode = keycode; list_add(&new_keyentry->list, &data->keytable); } else { kfree(new_keyentry); @@ -460,6 +449,10 @@ wbcir_setkeycode(struct input_dev *dev, return 0; } +/* + * Timer function to report keyup event some time after keydown is + * reported by the ISR. + */ static void wbcir_keyup(unsigned long cookie) { @@ -470,6 +463,11 @@ wbcir_keyup(unsigned long cookie) * data->keyup_jiffies is used to prevent a race condition if a * hardware interrupt occurs at this point and the keyup timer * event is moved further into the future as a result. + * + * The timer will then be reactivated and this function called + * again in the future. We need to exit gracefully in that case + * to allow the input subsystem to do its auto-repeat magic or + * a keyup event might follow immediately after the keydown. */ spin_lock_irqsave(&wbcir_lock, flags); @@ -534,7 +532,7 @@ set_timer: static void wbcir_reset_irdata(struct wbcir_data *data) { - memset(&data->irdata, 0, sizeof(data->irdata)); + memset(data->irdata, 0, sizeof(data->irdata)); data->irdata_count = 0; data->irdata_off = 0; data->irdata_error = 0; @@ -544,9 +542,13 @@ wbcir_reset_irdata(struct wbcir_data *da static void add_irdata_bit(struct wbcir_data *data, int set) { + if (data->irdata_count >= sizeof(data->irdata) * 8) { + data->irdata_error = 1; + return; + } + if (set) - data->irdata[data->irdata_count / 8] |= - 0x01 << (data->irdata_count % 8); + __set_bit(data->irdata_count, data->irdata); data->irdata_count++; } @@ -563,8 +565,7 @@ get_bits(struct wbcir_data *data, int co while (count > 0) { val <<= 1; - if (data->irdata[data->irdata_off / 8] & - (0x01 << (data->irdata_off % 8))) + if (test_bit(data->irdata_off, data->irdata)) val |= 0x1; count--; data->irdata_off++; @@ -893,10 +894,10 @@ wbcir_parse_nec(struct device *dev, stru return; } - address1 = wbcir_revbyte(get_bits(data, 8)); - address2 = wbcir_revbyte(get_bits(data, 8)); - command1 = wbcir_revbyte(get_bits(data, 8)); - command2 = wbcir_revbyte(get_bits(data, 8)); + address1 = bitrev8(get_bits(data, 8)); + address2 = bitrev8(get_bits(data, 8)); + command1 = bitrev8(get_bits(data, 8)); + command2 = bitrev8(get_bits(data, 8)); /* Sanity check */ if (data->irdata_error) { @@ -988,8 +989,8 @@ wbcir_irq_handler(int irqno, void *cooki outb(WBCIR_RX_DISABLE, data->sbase + WBCIR_REG_SP3_ASCR); dev_dbg(dev, "IRDATA:\n"); - for (i = 0; i < data->irdata_count; i += 8) - dev_dbg(dev, "0x%02X\n", data->irdata[i/8]); + for (i = 0; i < data->irdata_count; i += BITS_PER_LONG) + dev_dbg(dev, "0x%08lX\n", data->irdata[i/BITS_PER_LONG]); switch (protocol) { case IR_PROTOCOL_RC5: @@ -1068,12 +1069,12 @@ wbcir_shutdown(struct acpi_device *devic mask[0] = mask[1] = mask[2] = mask[3] = 0xFF; - match[1] = wbcir_revbyte((wake_sc & 0xFF)); + match[1] = bitrev8((wake_sc & 0xFF)); match[0] = ~match[1]; - match[3] = wbcir_revbyte((wake_sc & 0xFF00) >> 8); + match[3] = bitrev8((wake_sc & 0xFF00) >> 8); if (wake_sc > 0xFFFF) - match[2] = wbcir_revbyte((wake_sc & 0xFF0000) >> 16); + match[2] = bitrev8((wake_sc & 0xFF0000) >> 16); else match[2] = ~match[3]; @@ -1683,7 +1684,7 @@ wbcir_exit(void) acpi_bus_unregister_driver(&wbcir_driver); } -MODULE_AUTHOR("David Härdeman <david@xxxxxxxxxxx>"); +MODULE_AUTHOR("David Härdeman <david@xxxxxxxxxxx>"); MODULE_DESCRIPTION("Winbond SuperI/O Consumer IR Driver"); MODULE_LICENSE("GPL"); _ Patches currently in -mm which might be from david@xxxxxxxxxxx are acpi-reintroduce-acpi_device_ops-shutdown-method.patch add-a-driver-for-the-winbond-wpcd376i-ir-functionality.patch add-a-driver-for-the-winbond-wpcd376i-ir-functionality-update.patch -- To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html