Commit d6879837 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: remove scan_keyb driver
  Input: i8042 - fix AUX IRQ delivery check
  Input: wistron - add support for Fujitsu-Siemens Amilo D88x0
  Input: inport - use correct config option for ATIXL
  Input: HIL - handle erros from input_register_device()
  Input: tsdev - schedule removal
  Input: add Atlas button driver
  Input: ads7846 - be more compatible with the hwmon framework
  Input: ads7846 - detect pen up from GPIO state
  Input: ads7846 - select correct SPI mode
  Input: ads7846 - switch to using hrtimer
  Input: ads7846 - optionally leave Vref on during differential measurements
  Input: ads7846 - pluggable filtering logic
  Input: gpio-keys - keyboard driver for GPIO buttons
  Input: hid-ff - add support for Logitech Momo racing wheel
  Input: i8042 - really suppress ACK/NAK during panic blink
  Input: pc110pad - return proper error
parents 412ecd77 2a598df5
......@@ -319,3 +319,18 @@ Why: In kernel tree version of driver is unmaintained. Sk98lin driver
replaced by the skge driver.
Who: Stephen Hemminger <shemminger@osdl.org>
---------------------------
What: Compaq touchscreen device emulation
When: Oct 2007
Files: drivers/input/tsdev.c
Why: The code says it was obsolete when it was written in 2001.
tslib is a userspace library which does anything tsdev can do and
much more besides in userspace where this code belongs. There is no
longer any need for tsdev and applications should have converted to
use tslib by now.
The name "tsdev" is also extremely confusing and lots of people have
it loaded when they don't need/use it.
Who: Richard Purdie <rpurdie@rpsys.net>
---------------------------
/*
* $Id: scan_keyb.c,v 1.2 2000/07/04 06:24:42 yaegashi Exp $
* Copyright (C) 2000 YAEGASHI Takeshi
* Generic scan keyboard driver
*/
#include <linux/spinlock.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/mm.h>
#include <linux/signal.h>
#include <linux/init.h>
#include <linux/kbd_ll.h>
#include <linux/delay.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/kbd_kern.h>
#include <linux/timer.h>
#define SCANHZ (HZ/20)
struct scan_keyboard {
struct scan_keyboard *next;
int (*scan)(unsigned char *buffer);
const unsigned char *table;
unsigned char *s0, *s1;
int length;
};
static int scan_jiffies=0;
static struct scan_keyboard *keyboards=NULL;
struct timer_list scan_timer;
static void check_kbd(const unsigned char *table,
unsigned char *new, unsigned char *old, int length)
{
int need_tasklet_schedule=0;
unsigned int xor, bit;
while(length-->0) {
if((xor=*new^*old)==0) {
table+=8;
}
else {
for(bit=0x01; bit<0x100; bit<<=1) {
if(xor&bit) {
handle_scancode(*table, !(*new&bit));
need_tasklet_schedule=1;
#if 0
printk("0x%x %s\n", *table, (*new&bit)?"released":"pressed");
#endif
}
table++;
}
}
new++; old++;
}
if(need_tasklet_schedule)
tasklet_schedule(&keyboard_tasklet);
}
static void scan_kbd(unsigned long dummy)
{
struct scan_keyboard *kbd;
scan_jiffies++;
for(kbd=keyboards; kbd!=NULL; kbd=kbd->next) {
if(scan_jiffies&1) {
if(!kbd->scan(kbd->s0))
check_kbd(kbd->table,
kbd->s0, kbd->s1, kbd->length);
else
memcpy(kbd->s0, kbd->s1, kbd->length);
}
else {
if(!kbd->scan(kbd->s1))
check_kbd(kbd->table,
kbd->s1, kbd->s0, kbd->length);
else
memcpy(kbd->s1, kbd->s0, kbd->length);
}
}
init_timer(&scan_timer);
scan_timer.expires = jiffies + SCANHZ;
scan_timer.data = 0;
scan_timer.function = scan_kbd;
add_timer(&scan_timer);
}
int register_scan_keyboard(int (*scan)(unsigned char *buffer),
const unsigned char *table,
int length)
{
struct scan_keyboard *kbd;
kbd = kmalloc(sizeof(struct scan_keyboard), GFP_KERNEL);
if (kbd == NULL)
goto error_out;
kbd->scan=scan;
kbd->table=table;
kbd->length=length;
kbd->s0 = kmalloc(length, GFP_KERNEL);
if (kbd->s0 == NULL)
goto error_free_kbd;
kbd->s1 = kmalloc(length, GFP_KERNEL);
if (kbd->s1 == NULL)
goto error_free_s0;
memset(kbd->s0, -1, kbd->length);
memset(kbd->s1, -1, kbd->length);
kbd->next=keyboards;
keyboards=kbd;
return 0;
error_free_s0:
kfree(kbd->s0);
error_free_kbd:
kfree(kbd);
error_out:
return -ENOMEM;
}
void __init scan_kbd_init(void)
{
init_timer(&scan_timer);
scan_timer.expires = jiffies + SCANHZ;
scan_timer.data = 0;
scan_timer.function = scan_kbd;
add_timer(&scan_timer);
printk(KERN_INFO "Generic scan keyboard driver initialized\n");
}
#ifndef __DRIVER_CHAR_SCAN_KEYB_H
#define __DRIVER_CHAR_SCAN_KEYB_H
/*
* $Id: scan_keyb.h,v 1.1 2000/06/10 21:45:30 yaegashi Exp $
* Copyright (C) 2000 YAEGASHI Takeshi
* Generic scan keyboard driver
*/
int register_scan_keyboard(int (*scan)(unsigned char *buffer),
const unsigned char *table,
int length);
void __init scan_kbd_init(void);
#endif
......@@ -135,12 +135,12 @@ config KEYBOARD_STOWAWAY
config KEYBOARD_CORGI
tristate "Corgi keyboard"
depends on PXA_SHARPSL
default y
default y
help
Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx
Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx
series of PDAs.
To compile this driver as a module, choose M here: the
To compile this driver as a module, choose M here: the
module will be called corgikbd.
config KEYBOARD_SPITZ
......@@ -214,4 +214,17 @@ config KEYBOARD_AAED2000
To compile this driver as a module, choose M here: the
module will be called aaed2000_kbd.
config KEYBOARD_GPIO
tristate "Buttons on CPU GPIOs (PXA)"
depends on ARCH_PXA
help
This driver implements support for buttons connected
directly to GPIO pins of PXA CPUs.
Say Y here if your device has buttons connected
directly to GPIO pins of the CPU.
To compile this driver as a module, choose M here: the
module will be called gpio-keys.
endif
......@@ -16,6 +16,7 @@ obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o
obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o
obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o
obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o
obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
/*
* Driver for keys on GPIO lines capable of generating interrupts.
*
* Copyright 2005 Phil Blundell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/hardware.h>
#include <asm/hardware/gpio_keys.h>
static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
{
int i;
struct platform_device *pdev = dev_id;
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
struct input_dev *input = platform_get_drvdata(pdev);
for (i = 0; i < pdata->nbuttons; i++) {
int gpio = pdata->buttons[i].gpio;
if (irq == IRQ_GPIO(gpio)) {
int state = ((GPLR(gpio) & GPIO_bit(gpio)) ? 1 : 0) ^ (pdata->buttons[i].active_low);
input_report_key(input, pdata->buttons[i].keycode, state);
input_sync(input);
}
}
return IRQ_HANDLED;
}
static int __devinit gpio_keys_probe(struct platform_device *pdev)
{
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
struct input_dev *input;
int i, error;
input = input_allocate_device();
if (!input)
return -ENOMEM;
platform_set_drvdata(pdev, input);
input->evbit[0] = BIT(EV_KEY);
input->name = pdev->name;
input->phys = "gpio-keys/input0";
input->cdev.dev = &pdev->dev;
input->private = pdata;
input->id.bustype = BUS_HOST;
input->id.vendor = 0x0001;
input->id.product = 0x0001;
input->id.version = 0x0100;
for (i = 0; i < pdata->nbuttons; i++) {
int code = pdata->buttons[i].keycode;
int irq = IRQ_GPIO(pdata->buttons[i].gpio);
set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
error = request_irq(irq, gpio_keys_isr, SA_SAMPLE_RANDOM,
pdata->buttons[i].desc ? pdata->buttons[i].desc : "gpio_keys",
pdev);
if (error) {
printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n", irq, ret);
goto fail;
}
set_bit(code, input->keybit);
}
error = input_register_device(input);
if (error) {
printk(KERN_ERR "Unable to register gpio-keys input device\n");
goto fail;
}
return 0;
fail:
for (i = i - 1; i >= 0; i--)
free_irq(IRQ_GPIO(pdata->buttons[i].gpio), pdev);
input_free_device(input);
return error;
}
static int __devexit gpio_keys_remove(struct platform_device *pdev)
{
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
struct input_dev *input = platform_get_drvdata(pdev);
int i;
for (i = 0; i < pdata->nbuttons; i++) {
int irq = IRQ_GPIO(pdata->buttons[i].gpio);
free_irq(irq, pdev);
}
input_unregister_device(input);
return 0;
}
struct platform_driver gpio_keys_device_driver = {
.probe = gpio_keys_probe,
.remove = __devexit_p(gpio_keys_remove),
.driver = {
.name = "gpio-keys",
}
};
static int __init gpio_keys_init(void)
{
return platform_driver_register(&gpio_keys_device_driver);
}
static void __exit gpio_keys_exit(void)
{
platform_driver_unregister(&gpio_keys_device_driver);
}
module_init(gpio_keys_init);
module_exit(gpio_keys_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>");
MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
......@@ -6,10 +6,10 @@
* Copyright (C) 1999-2006 Helge Deller <deller@gmx.de>
*
* Very basic HP Human Interface Loop (HIL) driver.
* This driver handles the keyboard on HP300 (m68k) and on some
* This driver handles the keyboard on HP300 (m68k) and on some
* HP700 (parisc) series machines.
*
*
*
* This file is subject to the terms and conditions of the GNU General Public
* License version 2. See the file COPYING in the main directory of this
* archive for more details.
......@@ -64,9 +64,9 @@ MODULE_LICENSE("GPL v2");
#endif
/* HIL helper functions */
#define hil_busy() (hil_readb(HILBASE + HIL_CMD) & HIL_BUSY)
#define hil_data_available() (hil_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY)
#define hil_status() (hil_readb(HILBASE + HIL_CMD))
......@@ -75,7 +75,7 @@ MODULE_LICENSE("GPL v2");
#define hil_write_data(x) do { hil_writeb((x), HILBASE + HIL_DATA); } while (0)
/* HIL constants */
#define HIL_BUSY 0x02
#define HIL_DATA_RDY 0x01
......@@ -86,10 +86,10 @@ MODULE_LICENSE("GPL v2");
#define HIL_INTON 0x5C /* Turn on interrupts. */
#define HIL_INTOFF 0x5D /* Turn off interrupts. */
#define HIL_READKBDSADR 0xF9
#define HIL_WRITEKBDSADR 0xE9
#define HIL_READKBDSADR 0xF9
#define HIL_WRITEKBDSADR 0xE9
static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] =
static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] =
{ HIL_KEYCODES_SET1 };
/* HIL structure */
......@@ -97,11 +97,11 @@ static struct {
struct input_dev *dev;
unsigned int curdev;
unsigned char s;
unsigned char c;
int valid;
unsigned char data[16];
unsigned int ptr;
spinlock_t lock;
......@@ -115,7 +115,7 @@ static void poll_finished(void)
int down;
int key;
unsigned char scode;
switch (hil_dev.data[0]) {
case 0x40:
down = (hil_dev.data[1] & 1) == 0;
......@@ -127,6 +127,7 @@ static void poll_finished(void)
hil_dev.curdev = 0;
}
static inline void handle_status(unsigned char s, unsigned char c)
{
if (c & 0x8) {
......@@ -143,6 +144,7 @@ static inline void handle_status(unsigned char s, unsigned char c)
}
}
static inline void handle_data(unsigned char s, unsigned char c)
{
if (hil_dev.curdev) {
......@@ -152,13 +154,11 @@ static inline void handle_data(unsigned char s, unsigned char c)
}
/*
* Handle HIL interrupts.
*/
/* handle HIL interrupts */
static irqreturn_t hil_interrupt(int irq, void *handle)
{
unsigned char s, c;
s = hil_status();
c = hil_read_data();
......@@ -179,10 +179,8 @@ static irqreturn_t hil_interrupt(int irq, void *handle)
return IRQ_HANDLED;
}
/*
* Send a command to the HIL
*/
/* send a command to the HIL */
static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
{
unsigned long flags;
......@@ -200,16 +198,14 @@ static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
}
/*
* Initialise HIL.
*/
/* initialise HIL */
static int __init
hil_keyb_init(void)
{
unsigned char c;
unsigned int i, kbid;
wait_queue_head_t hil_wait;
int err;
if (hil_dev.dev) {
return -ENODEV; /* already initialized */
......@@ -219,15 +215,25 @@ hil_keyb_init(void)
if (!hil_dev.dev)
return -ENOMEM;
hil_dev.dev->private = &hil_dev;
#if defined(CONFIG_HP300)
if (!hwreg_present((void *)(HILBASE + HIL_DATA)))
return -ENODEV;
request_region(HILBASE+HIL_DATA, 2, "hil");
if (!hwreg_present((void *)(HILBASE + HIL_DATA))) {
printk(KERN_ERR "HIL: hardware register was not found\n");
err = -ENODEV;
goto err1;
}
if (!request_region(HILBASE + HIL_DATA, 2, "hil")) {
printk(KERN_ERR "HIL: IOPORT region already used\n");
err = -EIO;
goto err1;
}
#endif
request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id);
err = request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id);
if (err) {
printk(KERN_ERR "HIL: Can't get IRQ\n");
goto err2;
}
/* Turn on interrupts */
hil_do(HIL_INTON, NULL, 0);
......@@ -239,47 +245,63 @@ hil_keyb_init(void)
init_waitqueue_head(&hil_wait);
wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ);
if (!hil_dev.valid) {
printk(KERN_WARNING "HIL: timed out, assuming no keyboard present.\n");
printk(KERN_WARNING "HIL: timed out, assuming no keyboard present\n");
}
c = hil_dev.c;
c = hil_dev.c;
hil_dev.valid = 0;
if (c == 0) {
kbid = -1;
printk(KERN_WARNING "HIL: no keyboard present.\n");
printk(KERN_WARNING "HIL: no keyboard present\n");
} else {
kbid = ffz(~c);
/* printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid); */
printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid);
}
/* set it to raw mode */
c = 0;
hil_do(HIL_WRITEKBDSADR, &c, 1);
for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++)
if (hphilkeyb_keycode[i] != KEY_RESERVED)
set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit);
hil_dev.dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
hil_dev.dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
hil_dev.dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
hil_dev.dev->keycodesize = sizeof(hphilkeyb_keycode[0]);
hil_dev.dev->keycode = hphilkeyb_keycode;
hil_dev.dev->name = "HIL keyboard";
hil_dev.dev->phys = "hpkbd/input0";
hil_dev.dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
hil_dev.dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
hil_dev.dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
hil_dev.dev->keycodesize= sizeof(hphilkeyb_keycode[0]);
hil_dev.dev->keycode = hphilkeyb_keycode;
hil_dev.dev->name = "HIL keyboard";
hil_dev.dev->phys = "hpkbd/input0";
hil_dev.dev->id.bustype = BUS_HIL;
hil_dev.dev->id.vendor = PCI_VENDOR_ID_HP;
hil_dev.dev->id.product = 0x0001;
hil_dev.dev->id.version = 0x0010;
input_register_device(hil_dev.dev);
err = input_register_device(hil_dev.dev);
if (err) {
printk(KERN_ERR "HIL: Can't register device\n");
goto err3;
}
printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n",
hil_dev.dev->name, kbid, HILBASE, HIL_IRQ);
hil_dev.dev->name, kbid, HILBASE, HIL_IRQ);
return 0;
err3:
hil_do(HIL_INTOFF, NULL, 0);
disable_irq(HIL_IRQ);
free_irq(HIL_IRQ, hil_dev.dev_id);
err2:
release_region(HILBASE + HIL_DATA, 2);
err1:
input_free_device(hil_dev.dev);
hil_dev.dev = NULL;
return err;
}
#if defined(CONFIG_PARISC)
static int __init
hil_init_chip(struct parisc_device *dev)
......@@ -292,7 +314,7 @@ hil_init_chip(struct parisc_device *dev)
hil_base = dev->hpa.start;
hil_irq = dev->irq;
hil_dev.dev_id = dev;