diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-11 14:50:24 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-11 14:50:24 -0500 |
commit | d68798374bcf5cd4a19105b86d96121651b3c8cb (patch) | |
tree | 5e7432adf2b61f1497a4c3138c969e8664c54b6e | |
parent | 412ecd7751a2653ab17df39a1dc3565a548633fd (diff) | |
parent | 2a598df595d33be0f12e37ef5df75eff13511d07 (diff) |
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
-rw-r--r-- | Documentation/feature-removal-schedule.txt | 15 | ||||
-rw-r--r-- | drivers/char/scan_keyb.c | 149 | ||||
-rw-r--r-- | drivers/char/scan_keyb.h | 15 | ||||
-rw-r--r-- | drivers/input/keyboard/Kconfig | 19 | ||||
-rw-r--r-- | drivers/input/keyboard/Makefile | 5 | ||||
-rw-r--r-- | drivers/input/keyboard/gpio_keys.c | 147 | ||||
-rw-r--r-- | drivers/input/keyboard/hilkbd.c | 114 | ||||
-rw-r--r-- | drivers/input/misc/Kconfig | 10 | ||||
-rw-r--r-- | drivers/input/misc/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/misc/atlas_btns.c | 170 | ||||
-rw-r--r-- | drivers/input/misc/wistron_btns.c | 20 | ||||
-rw-r--r-- | drivers/input/mouse/inport.c | 2 | ||||
-rw-r--r-- | drivers/input/mouse/pc110pad.c | 2 | ||||
-rw-r--r-- | drivers/input/serio/i8042.c | 12 | ||||
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 9 | ||||
-rw-r--r-- | drivers/input/touchscreen/ads7846.c | 581 | ||||
-rw-r--r-- | drivers/input/tsdev.c | 4 | ||||
-rw-r--r-- | drivers/usb/input/hid-ff.c | 1 | ||||
-rw-r--r-- | drivers/usb/input/hid-lgff.c | 1 | ||||
-rw-r--r-- | include/asm-arm/hardware/gpio_keys.h | 17 | ||||
-rw-r--r-- | include/linux/spi/ads7846.h | 12 |
21 files changed, 889 insertions, 417 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 8247a4b79d09..c585aa8d62b4 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -319,3 +319,18 @@ Why: In kernel tree version of driver is unmaintained. Sk98lin driver | |||
319 | replaced by the skge driver. | 319 | replaced by the skge driver. |
320 | Who: Stephen Hemminger <shemminger@osdl.org> | 320 | Who: Stephen Hemminger <shemminger@osdl.org> |
321 | 321 | ||
322 | --------------------------- | ||
323 | |||
324 | What: Compaq touchscreen device emulation | ||
325 | When: Oct 2007 | ||
326 | Files: drivers/input/tsdev.c | ||
327 | Why: The code says it was obsolete when it was written in 2001. | ||
328 | tslib is a userspace library which does anything tsdev can do and | ||
329 | much more besides in userspace where this code belongs. There is no | ||
330 | longer any need for tsdev and applications should have converted to | ||
331 | use tslib by now. | ||
332 | The name "tsdev" is also extremely confusing and lots of people have | ||
333 | it loaded when they don't need/use it. | ||
334 | Who: Richard Purdie <rpurdie@rpsys.net> | ||
335 | |||
336 | --------------------------- | ||
diff --git a/drivers/char/scan_keyb.c b/drivers/char/scan_keyb.c deleted file mode 100644 index 2b5bb4f5754d..000000000000 --- a/drivers/char/scan_keyb.c +++ /dev/null | |||
@@ -1,149 +0,0 @@ | |||
1 | /* | ||
2 | * $Id: scan_keyb.c,v 1.2 2000/07/04 06:24:42 yaegashi Exp $ | ||
3 | * Copyright (C) 2000 YAEGASHI Takeshi | ||
4 | * Generic scan keyboard driver | ||
5 | */ | ||
6 | |||
7 | #include <linux/spinlock.h> | ||
8 | #include <linux/sched.h> | ||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/tty.h> | ||
11 | #include <linux/mm.h> | ||
12 | #include <linux/signal.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/kbd_ll.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/random.h> | ||
17 | #include <linux/poll.h> | ||
18 | #include <linux/miscdevice.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/kbd_kern.h> | ||
21 | #include <linux/timer.h> | ||
22 | |||
23 | #define SCANHZ (HZ/20) | ||
24 | |||
25 | struct scan_keyboard { | ||
26 | struct scan_keyboard *next; | ||
27 | int (*scan)(unsigned char *buffer); | ||
28 | const unsigned char *table; | ||
29 | unsigned char *s0, *s1; | ||
30 | int length; | ||
31 | }; | ||
32 | |||
33 | static int scan_jiffies=0; | ||
34 | static struct scan_keyboard *keyboards=NULL; | ||
35 | struct timer_list scan_timer; | ||
36 | |||
37 | static void check_kbd(const unsigned char *table, | ||
38 | unsigned char *new, unsigned char *old, int length) | ||
39 | { | ||
40 | int need_tasklet_schedule=0; | ||
41 | unsigned int xor, bit; | ||
42 | |||
43 | while(length-->0) { | ||
44 | if((xor=*new^*old)==0) { | ||
45 | table+=8; | ||
46 | } | ||
47 | else { | ||
48 | for(bit=0x01; bit<0x100; bit<<=1) { | ||
49 | if(xor&bit) { | ||
50 | handle_scancode(*table, !(*new&bit)); | ||
51 | need_tasklet_schedule=1; | ||
52 | #if 0 | ||
53 | printk("0x%x %s\n", *table, (*new&bit)?"released":"pressed"); | ||
54 | #endif | ||
55 | } | ||
56 | table++; | ||
57 | } | ||
58 | } | ||
59 | new++; old++; | ||
60 | } | ||
61 | |||
62 | if(need_tasklet_schedule) | ||
63 | tasklet_schedule(&keyboard_tasklet); | ||
64 | } | ||
65 | |||
66 | |||
67 | static void scan_kbd(unsigned long dummy) | ||
68 | { | ||
69 | struct scan_keyboard *kbd; | ||
70 | |||
71 | scan_jiffies++; | ||
72 | |||
73 | for(kbd=keyboards; kbd!=NULL; kbd=kbd->next) { | ||
74 | if(scan_jiffies&1) { | ||
75 | if(!kbd->scan(kbd->s0)) | ||
76 | check_kbd(kbd->table, | ||
77 | kbd->s0, kbd->s1, kbd->length); | ||
78 | else | ||
79 | memcpy(kbd->s0, kbd->s1, kbd->length); | ||
80 | } | ||
81 | else { | ||
82 | if(!kbd->scan(kbd->s1)) | ||
83 | check_kbd(kbd->table, | ||
84 | kbd->s1, kbd->s0, kbd->length); | ||
85 | else | ||
86 | memcpy(kbd->s1, kbd->s0, kbd->length); | ||
87 | } | ||
88 | |||
89 | } | ||
90 | |||
91 | init_timer(&scan_timer); | ||
92 | scan_timer.expires = jiffies + SCANHZ; | ||
93 | scan_timer.data = 0; | ||
94 | scan_timer.function = scan_kbd; | ||
95 | add_timer(&scan_timer); | ||
96 | } | ||
97 | |||
98 | |||
99 | int register_scan_keyboard(int (*scan)(unsigned char *buffer), | ||
100 | const unsigned char *table, | ||
101 | int length) | ||
102 | { | ||
103 | struct scan_keyboard *kbd; | ||
104 | |||
105 | kbd = kmalloc(sizeof(struct scan_keyboard), GFP_KERNEL); | ||
106 | if (kbd == NULL) | ||
107 | goto error_out; | ||
108 | |||
109 | kbd->scan=scan; | ||
110 | kbd->table=table; | ||
111 | kbd->length=length; | ||
112 | |||
113 | kbd->s0 = kmalloc(length, GFP_KERNEL); | ||
114 | if (kbd->s0 == NULL) | ||
115 | goto error_free_kbd; | ||
116 | |||
117 | kbd->s1 = kmalloc(length, GFP_KERNEL); | ||
118 | if (kbd->s1 == NULL) | ||
119 | goto error_free_s0; | ||
120 | |||
121 | memset(kbd->s0, -1, kbd->length); | ||
122 | memset(kbd->s1, -1, kbd->length); | ||
123 | |||
124 | kbd->next=keyboards; | ||
125 | keyboards=kbd; | ||
126 | |||
127 | return 0; | ||
128 | |||
129 | error_free_s0: | ||
130 | kfree(kbd->s0); | ||
131 | |||
132 | error_free_kbd: | ||
133 | kfree(kbd); | ||
134 | |||
135 | error_out: | ||
136 | return -ENOMEM; | ||
137 | } | ||
138 | |||
139 | |||
140 | void __init scan_kbd_init(void) | ||
141 | { | ||
142 | init_timer(&scan_timer); | ||
143 | scan_timer.expires = jiffies + SCANHZ; | ||
144 | scan_timer.data = 0; | ||
145 | scan_timer.function = scan_kbd; | ||
146 | add_timer(&scan_timer); | ||
147 | |||
148 | printk(KERN_INFO "Generic scan keyboard driver initialized\n"); | ||
149 | } | ||
diff --git a/drivers/char/scan_keyb.h b/drivers/char/scan_keyb.h deleted file mode 100644 index b4b611290a00..000000000000 --- a/drivers/char/scan_keyb.h +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | #ifndef __DRIVER_CHAR_SCAN_KEYB_H | ||
2 | #define __DRIVER_CHAR_SCAN_KEYB_H | ||
3 | /* | ||
4 | * $Id: scan_keyb.h,v 1.1 2000/06/10 21:45:30 yaegashi Exp $ | ||
5 | * Copyright (C) 2000 YAEGASHI Takeshi | ||
6 | * Generic scan keyboard driver | ||
7 | */ | ||
8 | |||
9 | int register_scan_keyboard(int (*scan)(unsigned char *buffer), | ||
10 | const unsigned char *table, | ||
11 | int length); | ||
12 | |||
13 | void __init scan_kbd_init(void); | ||
14 | |||
15 | #endif | ||
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 049f2f544e75..1b81a72e19d9 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -135,12 +135,12 @@ config KEYBOARD_STOWAWAY | |||
135 | config KEYBOARD_CORGI | 135 | config KEYBOARD_CORGI |
136 | tristate "Corgi keyboard" | 136 | tristate "Corgi keyboard" |
137 | depends on PXA_SHARPSL | 137 | depends on PXA_SHARPSL |
138 | default y | 138 | default y |
139 | help | 139 | help |
140 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx | 140 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx |
141 | series of PDAs. | 141 | series of PDAs. |
142 | 142 | ||
143 | To compile this driver as a module, choose M here: the | 143 | To compile this driver as a module, choose M here: the |
144 | module will be called corgikbd. | 144 | module will be called corgikbd. |
145 | 145 | ||
146 | config KEYBOARD_SPITZ | 146 | config KEYBOARD_SPITZ |
@@ -214,4 +214,17 @@ config KEYBOARD_AAED2000 | |||
214 | To compile this driver as a module, choose M here: the | 214 | To compile this driver as a module, choose M here: the |
215 | module will be called aaed2000_kbd. | 215 | module will be called aaed2000_kbd. |
216 | 216 | ||
217 | config KEYBOARD_GPIO | ||
218 | tristate "Buttons on CPU GPIOs (PXA)" | ||
219 | depends on ARCH_PXA | ||
220 | help | ||
221 | This driver implements support for buttons connected | ||
222 | directly to GPIO pins of PXA CPUs. | ||
223 | |||
224 | Say Y here if your device has buttons connected | ||
225 | directly to GPIO pins of the CPU. | ||
226 | |||
227 | To compile this driver as a module, choose M here: the | ||
228 | module will be called gpio-keys. | ||
229 | |||
217 | endif | 230 | endif |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 568797907347..586a0fe53be6 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -16,6 +16,7 @@ obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o | |||
16 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o | 16 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o |
17 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o | 17 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o |
18 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o | 18 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o |
19 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o | 19 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o |
20 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o | 20 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o |
21 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o | ||
21 | 22 | ||
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c new file mode 100644 index 000000000000..3a8f1b427a7f --- /dev/null +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -0,0 +1,147 @@ | |||
1 | /* | ||
2 | * Driver for keys on GPIO lines capable of generating interrupts. | ||
3 | * | ||
4 | * Copyright 2005 Phil Blundell | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/version.h> | ||
13 | |||
14 | #include <linux/init.h> | ||
15 | #include <linux/fs.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/irq.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/pm.h> | ||
20 | #include <linux/sysctl.h> | ||
21 | #include <linux/proc_fs.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/input.h> | ||
25 | #include <linux/irq.h> | ||
26 | |||
27 | #include <asm/arch/pxa-regs.h> | ||
28 | #include <asm/arch/hardware.h> | ||
29 | |||
30 | #include <asm/hardware/gpio_keys.h> | ||
31 | |||
32 | static irqreturn_t gpio_keys_isr(int irq, void *dev_id) | ||
33 | { | ||
34 | int i; | ||
35 | struct platform_device *pdev = dev_id; | ||
36 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
37 | struct input_dev *input = platform_get_drvdata(pdev); | ||
38 | |||
39 | for (i = 0; i < pdata->nbuttons; i++) { | ||
40 | int gpio = pdata->buttons[i].gpio; | ||
41 | if (irq == IRQ_GPIO(gpio)) { | ||
42 | int state = ((GPLR(gpio) & GPIO_bit(gpio)) ? 1 : 0) ^ (pdata->buttons[i].active_low); | ||
43 | |||
44 | input_report_key(input, pdata->buttons[i].keycode, state); | ||
45 | input_sync(input); | ||
46 | } | ||
47 | } | ||
48 | |||
49 | return IRQ_HANDLED; | ||
50 | } | ||
51 | |||
52 | static int __devinit gpio_keys_probe(struct platform_device *pdev) | ||
53 | { | ||
54 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
55 | struct input_dev *input; | ||
56 | int i, error; | ||
57 | |||
58 | input = input_allocate_device(); | ||
59 | if (!input) | ||
60 | return -ENOMEM; | ||
61 | |||
62 | platform_set_drvdata(pdev, input); | ||
63 | |||
64 | input->evbit[0] = BIT(EV_KEY); | ||
65 | |||
66 | input->name = pdev->name; | ||
67 | input->phys = "gpio-keys/input0"; | ||
68 | input->cdev.dev = &pdev->dev; | ||
69 | input->private = pdata; | ||
70 | |||
71 | input->id.bustype = BUS_HOST; | ||
72 | input->id.vendor = 0x0001; | ||
73 | input->id.product = 0x0001; | ||
74 | input->id.version = 0x0100; | ||
75 | |||
76 | for (i = 0; i < pdata->nbuttons; i++) { | ||
77 | int code = pdata->buttons[i].keycode; | ||
78 | int irq = IRQ_GPIO(pdata->buttons[i].gpio); | ||
79 | |||
80 | set_irq_type(irq, IRQ_TYPE_EDGE_BOTH); | ||
81 | error = request_irq(irq, gpio_keys_isr, SA_SAMPLE_RANDOM, | ||
82 | pdata->buttons[i].desc ? pdata->buttons[i].desc : "gpio_keys", | ||
83 | pdev); | ||
84 | if (error) { | ||
85 | printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n", irq, ret); | ||
86 | goto fail; | ||
87 | } | ||
88 | set_bit(code, input->keybit); | ||
89 | } | ||
90 | |||
91 | error = input_register_device(input); | ||
92 | if (error) { | ||
93 | printk(KERN_ERR "Unable to register gpio-keys input device\n"); | ||
94 | goto fail; | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | |||
99 | fail: | ||
100 | for (i = i - 1; i >= 0; i--) | ||
101 | free_irq(IRQ_GPIO(pdata->buttons[i].gpio), pdev); | ||
102 | |||
103 | input_free_device(input); | ||
104 | |||
105 | return error; | ||
106 | } | ||
107 | |||
108 | static int __devexit gpio_keys_remove(struct platform_device *pdev) | ||
109 | { | ||
110 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
111 | struct input_dev *input = platform_get_drvdata(pdev); | ||
112 | int i; | ||
113 | |||
114 | for (i = 0; i < pdata->nbuttons; i++) { | ||
115 | int irq = IRQ_GPIO(pdata->buttons[i].gpio); | ||
116 | free_irq(irq, pdev); | ||
117 | } | ||
118 | |||
119 | input_unregister_device(input); | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | struct platform_driver gpio_keys_device_driver = { | ||
125 | .probe = gpio_keys_probe, | ||
126 | .remove = __devexit_p(gpio_keys_remove), | ||
127 | .driver = { | ||
128 | .name = "gpio-keys", | ||
129 | } | ||
130 | }; | ||
131 | |||
132 | static int __init gpio_keys_init(void) | ||
133 | { | ||
134 | return platform_driver_register(&gpio_keys_device_driver); | ||
135 | } | ||
136 | |||
137 | static void __exit gpio_keys_exit(void) | ||
138 | { | ||
139 | platform_driver_unregister(&gpio_keys_device_driver); | ||
140 | } | ||
141 | |||
142 | module_init(gpio_keys_init); | ||
143 | module_exit(gpio_keys_exit); | ||
144 | |||
145 | MODULE_LICENSE("GPL"); | ||
146 | MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>"); | ||
147 | MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs"); | ||
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c index 35461eab2faf..255a6ec75a48 100644 --- a/drivers/input/keyboard/hilkbd.c +++ b/drivers/input/keyboard/hilkbd.c | |||
@@ -6,10 +6,10 @@ | |||
6 | * Copyright (C) 1999-2006 Helge Deller <deller@gmx.de> | 6 | * Copyright (C) 1999-2006 Helge Deller <deller@gmx.de> |
7 | * | 7 | * |
8 | * Very basic HP Human Interface Loop (HIL) driver. | 8 | * Very basic HP Human Interface Loop (HIL) driver. |
9 | * This driver handles the keyboard on HP300 (m68k) and on some | 9 | * This driver handles the keyboard on HP300 (m68k) and on some |
10 | * HP700 (parisc) series machines. | 10 | * HP700 (parisc) series machines. |
11 | * | 11 | * |
12 | * | 12 | * |
13 | * This file is subject to the terms and conditions of the GNU General Public | 13 | * This file is subject to the terms and conditions of the GNU General Public |
14 | * License version 2. See the file COPYING in the main directory of this | 14 | * License version 2. See the file COPYING in the main directory of this |
15 | * archive for more details. | 15 | * archive for more details. |
@@ -64,9 +64,9 @@ MODULE_LICENSE("GPL v2"); | |||
64 | #endif | 64 | #endif |
65 | 65 | ||
66 | 66 | ||
67 | 67 | ||
68 | /* HIL helper functions */ | 68 | /* HIL helper functions */ |
69 | 69 | ||
70 | #define hil_busy() (hil_readb(HILBASE + HIL_CMD) & HIL_BUSY) | 70 | #define hil_busy() (hil_readb(HILBASE + HIL_CMD) & HIL_BUSY) |
71 | #define hil_data_available() (hil_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY) | 71 | #define hil_data_available() (hil_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY) |
72 | #define hil_status() (hil_readb(HILBASE + HIL_CMD)) | 72 | #define hil_status() (hil_readb(HILBASE + HIL_CMD)) |
@@ -75,7 +75,7 @@ MODULE_LICENSE("GPL v2"); | |||
75 | #define hil_write_data(x) do { hil_writeb((x), HILBASE + HIL_DATA); } while (0) | 75 | #define hil_write_data(x) do { hil_writeb((x), HILBASE + HIL_DATA); } while (0) |
76 | 76 | ||
77 | /* HIL constants */ | 77 | /* HIL constants */ |
78 | 78 | ||
79 | #define HIL_BUSY 0x02 | 79 | #define HIL_BUSY 0x02 |
80 | #define HIL_DATA_RDY 0x01 | 80 | #define HIL_DATA_RDY 0x01 |
81 | 81 | ||
@@ -86,10 +86,10 @@ MODULE_LICENSE("GPL v2"); | |||
86 | #define HIL_INTON 0x5C /* Turn on interrupts. */ | 86 | #define HIL_INTON 0x5C /* Turn on interrupts. */ |
87 | #define HIL_INTOFF 0x5D /* Turn off interrupts. */ | 87 | #define HIL_INTOFF 0x5D /* Turn off interrupts. */ |
88 | 88 | ||
89 | #define HIL_READKBDSADR 0xF9 | 89 | #define HIL_READKBDSADR 0xF9 |
90 | #define HIL_WRITEKBDSADR 0xE9 | 90 | #define HIL_WRITEKBDSADR 0xE9 |
91 | 91 | ||
92 | static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] = | 92 | static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] = |
93 | { HIL_KEYCODES_SET1 }; | 93 | { HIL_KEYCODES_SET1 }; |
94 | 94 | ||
95 | /* HIL structure */ | 95 | /* HIL structure */ |
@@ -97,11 +97,11 @@ static struct { | |||
97 | struct input_dev *dev; | 97 | struct input_dev *dev; |
98 | 98 | ||
99 | unsigned int curdev; | 99 | unsigned int curdev; |
100 | 100 | ||
101 | unsigned char s; | 101 | unsigned char s; |
102 | unsigned char c; | 102 | unsigned char c; |
103 | int valid; | 103 | int valid; |
104 | 104 | ||
105 | unsigned char data[16]; | 105 | unsigned char data[16]; |
106 | unsigned int ptr; | 106 | unsigned int ptr; |
107 | spinlock_t lock; | 107 | spinlock_t lock; |
@@ -115,7 +115,7 @@ static void poll_finished(void) | |||
115 | int down; | 115 | int down; |
116 | int key; | 116 | int key; |
117 | unsigned char scode; | 117 | unsigned char scode; |
118 | 118 | ||
119 | switch (hil_dev.data[0]) { | 119 | switch (hil_dev.data[0]) { |
120 | case 0x40: | 120 | case 0x40: |
121 | down = (hil_dev.data[1] & 1) == 0; | 121 | down = (hil_dev.data[1] & 1) == 0; |
@@ -127,6 +127,7 @@ static void poll_finished(void) | |||
127 | hil_dev.curdev = 0; | 127 | hil_dev.curdev = 0; |
128 | } | 128 | } |
129 | 129 | ||
130 | |||
130 | static inline void handle_status(unsigned char s, unsigned char c) | 131 | static inline void handle_status(unsigned char s, unsigned char c) |
131 | { | 132 | { |
132 | if (c & 0x8) { | 133 | if (c & 0x8) { |
@@ -143,6 +144,7 @@ static inline void handle_status(unsigned char s, unsigned char c) | |||
143 | } | 144 | } |
144 | } | 145 | } |
145 | 146 | ||
147 | |||
146 | static inline void handle_data(unsigned char s, unsigned char c) | 148 | static inline void handle_data(unsigned char s, unsigned char c) |
147 | { | 149 | { |
148 | if (hil_dev.curdev) { | 150 | if (hil_dev.curdev) { |
@@ -152,13 +154,11 @@ static inline void handle_data(unsigned char s, unsigned char c) | |||
152 | } | 154 | } |
153 | 155 | ||
154 | 156 | ||
155 | /* | 157 | /* handle HIL interrupts */ |
156 | * Handle HIL interrupts. | ||
157 | */ | ||
158 | static irqreturn_t hil_interrupt(int irq, void *handle) | 158 | static irqreturn_t hil_interrupt(int irq, void *handle) |
159 | { | 159 | { |
160 | unsigned char s, c; | 160 | unsigned char s, c; |
161 | 161 | ||
162 | s = hil_status(); | 162 | s = hil_status(); |
163 | c = hil_read_data(); | 163 | c = hil_read_data(); |
164 | 164 | ||
@@ -179,10 +179,8 @@ static irqreturn_t hil_interrupt(int irq, void *handle) | |||
179 | return IRQ_HANDLED; | 179 | return IRQ_HANDLED; |
180 | } | 180 | } |
181 | 181 | ||
182 | /* | ||
183 | * Send a command to the HIL | ||
184 | */ | ||
185 | 182 | ||
183 | /* send a command to the HIL */ | ||
186 | static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) | 184 | static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) |
187 | { | 185 | { |
188 | unsigned long flags; | 186 | unsigned long flags; |
@@ -200,16 +198,14 @@ static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) | |||
200 | } | 198 | } |
201 | 199 | ||
202 | 200 | ||
203 | /* | 201 | /* initialise HIL */ |
204 | * Initialise HIL. | ||
205 | */ | ||
206 | |||
207 | static int __init | 202 | static int __init |
208 | hil_keyb_init(void) | 203 | hil_keyb_init(void) |
209 | { | 204 | { |
210 | unsigned char c; | 205 | unsigned char c; |
211 | unsigned int i, kbid; | 206 | unsigned int i, kbid; |
212 | wait_queue_head_t hil_wait; | 207 | wait_queue_head_t hil_wait; |
208 | int err; | ||
213 | 209 | ||
214 | if (hil_dev.dev) { | 210 | if (hil_dev.dev) { |
215 | return -ENODEV; /* already initialized */ | 211 | return -ENODEV; /* already initialized */ |
@@ -219,15 +215,25 @@ hil_keyb_init(void) | |||
219 | if (!hil_dev.dev) | 215 | if (!hil_dev.dev) |
220 | return -ENOMEM; | 216 | return -ENOMEM; |
221 | hil_dev.dev->private = &hil_dev; | 217 | hil_dev.dev->private = &hil_dev; |
222 | 218 | ||
223 | #if defined(CONFIG_HP300) | 219 | #if defined(CONFIG_HP300) |
224 | if (!hwreg_present((void *)(HILBASE + HIL_DATA))) | 220 | if (!hwreg_present((void *)(HILBASE + HIL_DATA))) { |
225 | return -ENODEV; | 221 | printk(KERN_ERR "HIL: hardware register was not found\n"); |
226 | 222 | err = -ENODEV; | |
227 | request_region(HILBASE+HIL_DATA, 2, "hil"); | 223 | goto err1; |
224 | } | ||
225 | if (!request_region(HILBASE + HIL_DATA, 2, "hil")) { | ||
226 | printk(KERN_ERR "HIL: IOPORT region already used\n"); | ||
227 | err = -EIO; | ||
228 | goto err1; | ||
229 | } | ||
228 | #endif | 230 | #endif |
229 | 231 | ||
230 | request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id); | 232 | err = request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id); |
233 | if (err) { | ||
234 | printk(KERN_ERR "HIL: Can't get IRQ\n"); | ||
235 | goto err2; | ||
236 | } | ||
231 | 237 | ||
232 | /* Turn on interrupts */ | 238 | /* Turn on interrupts */ |
233 | hil_do(HIL_INTON, NULL, 0); | 239 | hil_do(HIL_INTON, NULL, 0); |
@@ -239,47 +245,63 @@ hil_keyb_init(void) | |||
239 | init_waitqueue_head(&hil_wait); | 245 | init_waitqueue_head(&hil_wait); |
240 | wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ); | 246 | wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ); |
241 | if (!hil_dev.valid) { | 247 | if (!hil_dev.valid) { |
242 | printk(KERN_WARNING "HIL: timed out, assuming no keyboard present.\n"); | 248 | printk(KERN_WARNING "HIL: timed out, assuming no keyboard present\n"); |
243 | } | 249 | } |
244 | 250 | ||
245 | c = hil_dev.c; | 251 | c = hil_dev.c; |
246 | hil_dev.valid = 0; | 252 | hil_dev.valid = 0; |
247 | if (c == 0) { | 253 | if (c == 0) { |
248 | kbid = -1; | 254 | kbid = -1; |
249 | printk(KERN_WARNING "HIL: no keyboard present.\n"); | 255 | printk(KERN_WARNING "HIL: no keyboard present\n"); |
250 | } else { | 256 | } else { |
251 | kbid = ffz(~c); | 257 | kbid = ffz(~c); |
252 | /* printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid); */ | 258 | printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid); |
253 | } | 259 | } |
254 | 260 | ||
255 | /* set it to raw mode */ | 261 | /* set it to raw mode */ |
256 | c = 0; | 262 | c = 0; |
257 | hil_do(HIL_WRITEKBDSADR, &c, 1); | 263 | hil_do(HIL_WRITEKBDSADR, &c, 1); |
258 | 264 | ||
259 | for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++) | 265 | for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++) |
260 | if (hphilkeyb_keycode[i] != KEY_RESERVED) | 266 | if (hphilkeyb_keycode[i] != KEY_RESERVED) |
261 | set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit); | 267 | set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit); |
262 | 268 | ||
263 | hil_dev.dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | 269 | hil_dev.dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); |
264 | hil_dev.dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); | 270 | hil_dev.dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); |
265 | hil_dev.dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; | 271 | hil_dev.dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; |
266 | hil_dev.dev->keycodesize = sizeof(hphilkeyb_keycode[0]); | 272 | hil_dev.dev->keycodesize= sizeof(hphilkeyb_keycode[0]); |
267 | hil_dev.dev->keycode = hphilkeyb_keycode; | 273 | hil_dev.dev->keycode = hphilkeyb_keycode; |
268 | hil_dev.dev->name = "HIL keyboard"; | 274 | hil_dev.dev->name = "HIL keyboard"; |
269 | hil_dev.dev->phys = "hpkbd/input0"; | 275 | hil_dev.dev->phys = "hpkbd/input0"; |
270 | 276 | ||
271 | hil_dev.dev->id.bustype = BUS_HIL; | 277 | hil_dev.dev->id.bustype = BUS_HIL; |
272 | hil_dev.dev->id.vendor = PCI_VENDOR_ID_HP; | 278 | hil_dev.dev->id.vendor = PCI_VENDOR_ID_HP; |
273 | hil_dev.dev->id.product = 0x0001; | 279 | hil_dev.dev->id.product = 0x0001; |
274 | hil_dev.dev->id.version = 0x0010; | 280 | hil_dev.dev->id.version = 0x0010; |
275 | 281 | ||
276 | input_register_device(hil_dev.dev); | 282 | err = input_register_device(hil_dev.dev); |
283 | if (err) { | ||
284 | printk(KERN_ERR "HIL: Can't register device\n"); | ||
285 | goto err3; | ||
286 | } | ||
277 | printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n", | 287 | printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n", |
278 | hil_dev.dev->name, kbid, HILBASE, HIL_IRQ); | 288 | hil_dev.dev->name, kbid, HILBASE, HIL_IRQ); |
279 | 289 | ||
280 | return 0; | 290 | return 0; |
291 | |||
292 | err3: | ||
293 | hil_do(HIL_INTOFF, NULL, 0); | ||
294 | disable_irq(HIL_IRQ); | ||
295 | free_irq(HIL_IRQ, hil_dev.dev_id); | ||
296 | err2: | ||
297 | release_region(HILBASE + HIL_DATA, 2); | ||
298 | err1: | ||
299 | input_free_device(hil_dev.dev); | ||
300 | hil_dev.dev = NULL; | ||
301 | return err; | ||
281 | } | 302 | } |
282 | 303 | ||
304 | |||
283 | #if defined(CONFIG_PARISC) | 305 | #if defined(CONFIG_PARISC) |
284 | static int __init | 306 | static int __init |
285 | hil_init_chip(struct parisc_device *dev) | 307 | hil_init_chip(struct parisc_device *dev) |
@@ -292,7 +314,7 @@ hil_init_chip(struct parisc_device *dev) | |||
292 | hil_base = dev->hpa.start; | 314 | hil_base = dev->hpa.start; |
293 | hil_irq = dev->irq; | 315 | hil_irq = dev->irq; |
294 | hil_dev.dev_id = dev; | 316 | hil_dev.dev_id = dev; |
295 | 317 | ||
296 | printk(KERN_INFO "Found HIL bus at 0x%08lx, IRQ %d\n", hil_base, hil_irq); | 318 | printk(KERN_INFO "Found HIL bus at 0x%08lx, IRQ %d\n", hil_base, hil_irq); |
297 | 319 | ||
298 | return hil_keyb_init(); | 320 | return hil_keyb_init(); |
@@ -313,9 +335,6 @@ static struct parisc_driver hil_driver = { | |||
313 | #endif /* CONFIG_PARISC */ | 335 | #endif /* CONFIG_PARISC */ |
314 | 336 | ||
315 | 337 | ||
316 | |||
317 | |||
318 | |||
319 | static int __init hil_init(void) | 338 | static int __init hil_init(void) |
320 | { | 339 | { |
321 | #if defined(CONFIG_PARISC) | 340 | #if defined(CONFIG_PARISC) |
@@ -349,4 +368,3 @@ static void __exit hil_exit(void) | |||
349 | 368 | ||
350 | module_init(hil_init); | 369 | module_init(hil_init); |
351 | module_exit(hil_exit); | 370 | module_exit(hil_exit); |
352 | |||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index ba0e88c64e1e..41b42587f5e9 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -50,6 +50,16 @@ config INPUT_WISTRON_BTNS | |||
50 | To compile this driver as a module, choose M here: the module will | 50 | To compile this driver as a module, choose M here: the module will |
51 | be called wistron_btns. | 51 | be called wistron_btns. |
52 | 52 | ||
53 | config INPUT_ATLAS_BTNS | ||
54 | tristate "x86 Atlas button interface" | ||
55 | depends on X86 && ACPI | ||
56 | help | ||
57 | Say Y here for support of Atlas wallmount touchscreen buttons. | ||
58 | The events will show up as scancodes F1 through F9 via evdev. | ||
59 | |||
60 | To compile this driver as a module, choose M here: the module will | ||
61 | be called atlas_btns. | ||
62 | |||
53 | config INPUT_IXP4XX_BEEPER | 63 | config INPUT_IXP4XX_BEEPER |
54 | tristate "IXP4XX Beeper support" | 64 | tristate "IXP4XX Beeper support" |
55 | depends on ARCH_IXP4XX | 65 | depends on ARCH_IXP4XX |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 415c49178985..e0a8d58c9e9b 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -9,5 +9,6 @@ obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o | |||
9 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o | 9 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o |
10 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o | 10 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o |
11 | obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o | 11 | obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o |
12 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o | ||
12 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o | 13 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o |
13 | obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o | 14 | obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o |
diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c new file mode 100644 index 000000000000..0acc3a123604 --- /dev/null +++ b/drivers/input/misc/atlas_btns.c | |||
@@ -0,0 +1,170 @@ | |||
1 | /* | ||
2 | * atlas_btns.c - Atlas Wallmount Touchscreen ACPI Extras | ||
3 | * | ||
4 | * Copyright (C) 2006 Jaya Kumar | ||
5 | * Based on Toshiba ACPI by John Belmonte and ASUS ACPI | ||
6 | * This work was sponsored by CIS(M) Sdn Bhd. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/input.h> | ||
28 | #include <linux/types.h> | ||
29 | #include <asm/uaccess.h> | ||
30 | #include <acpi/acpi_drivers.h> | ||
31 | |||
32 | #define ACPI_ATLAS_NAME "Atlas ACPI" | ||
33 | #define ACPI_ATLAS_CLASS "Atlas" | ||
34 | #define ACPI_ATLAS_BUTTON_HID "ASIM0000" | ||
35 | |||
36 | static struct input_dev *input_dev; | ||
37 | |||
38 | /* button handling code */ | ||
39 | static acpi_status acpi_atlas_button_setup(acpi_handle region_handle, | ||
40 | u32 function, void *handler_context, void **return_context) | ||
41 | { | ||
42 | *return_context = | ||
43 | (function != ACPI_REGION_DEACTIVATE) ? handler_context : NULL; | ||
44 | |||
45 | return AE_OK; | ||
46 | } | ||
47 | |||
48 | static acpi_status acpi_atlas_button_handler(u32 function, | ||
49 | acpi_physical_address address, | ||
50 | u32 bit_width, acpi_integer *value, | ||
51 | void *handler_context, void *region_context) | ||
52 | { | ||
53 | acpi_status status; | ||
54 | int keycode; | ||
55 | |||
56 | if (function == ACPI_WRITE) { | ||
57 | keycode = KEY_F1 + (address & 0x0F); | ||
58 | input_report_key(input_dev, keycode, !(address & 0x10)); | ||
59 | input_sync(input_dev); | ||
60 | status = 0; | ||
61 | } else { | ||
62 | printk(KERN_WARNING "atlas: shrugged on unexpected function" | ||
63 | ":function=%x,address=%lx,value=%x\n", | ||
64 | function, (unsigned long)address, (u32)*value); | ||
65 | status = -EINVAL; | ||
66 | } | ||
67 | |||
68 | return status; | ||
69 | } | ||
70 | |||
71 | static int atlas_acpi_button_add(struct acpi_device *device) | ||
72 | { | ||
73 | acpi_status status; | ||
74 | int err; | ||
75 | |||
76 | input_dev = input_allocate_device(); | ||
77 | if (!input_dev) { | ||
78 | printk(KERN_ERR "atlas: unable to allocate input device\n"); | ||
79 | return -ENOMEM; | ||
80 | } | ||
81 | |||
82 | input_dev->name = "Atlas ACPI button driver"; | ||
83 | input_dev->phys = "ASIM0000/atlas/input0"; | ||
84 | input_dev->id.bustype = BUS_HOST; | ||
85 | input_dev->evbit[LONG(EV_KEY)] = BIT(EV_KEY); | ||
86 | |||
87 | set_bit(KEY_F1, input_dev->keybit); | ||
88 | set_bit(KEY_F2, input_dev->keybit); | ||
89 | set_bit(KEY_F3, input_dev->keybit); | ||
90 | set_bit(KEY_F4, input_dev->keybit); | ||
91 | set_bit(KEY_F5, input_dev->keybit); | ||
92 | set_bit(KEY_F6, input_dev->keybit); | ||
93 | set_bit(KEY_F7, input_dev->keybit); | ||
94 | set_bit(KEY_F8, input_dev->keybit); | ||
95 | set_bit(KEY_F9, input_dev->keybit); | ||
96 | |||
97 | err = input_register_device(input_dev); | ||
98 | if (err) { | ||
99 | printk(KERN_ERR "atlas: couldn't register input device\n"); | ||
100 | input_free_device(input_dev); | ||
101 | return err; | ||
102 | } | ||
103 | |||
104 | /* hookup button handler */ | ||
105 | status = acpi_install_address_space_handler(device->handle, | ||
106 | 0x81, &acpi_atlas_button_handler, | ||
107 | &acpi_atlas_button_setup, device); | ||
108 | if (ACPI_FAILURE(status)) { | ||
109 | printk(KERN_ERR "Atlas: Error installing addr spc handler\n"); | ||
110 | input_unregister_device(input_dev); | ||
111 | status = -EINVAL; | ||
112 | } | ||
113 | |||
114 | return status; | ||
115 | } | ||
116 | |||
117 | static int atlas_acpi_button_remove(struct acpi_device *device, int type) | ||
118 | { | ||
119 | acpi_status status; | ||
120 | |||
121 | status = acpi_remove_address_space_handler(device->handle, | ||
122 | 0x81, &acpi_atlas_button_handler); | ||
123 | if (ACPI_FAILURE(status)) { | ||
124 | printk(KERN_ERR "Atlas: Error removing addr spc handler\n"); | ||
125 | status = -EINVAL; | ||
126 | } | ||
127 | |||
128 | input_unregister_device(input_dev); | ||
129 | |||
130 | return status; | ||
131 | } | ||
132 | |||
133 | static struct acpi_driver atlas_acpi_driver = { | ||
134 | .name = ACPI_ATLAS_NAME, | ||
135 | .class = ACPI_ATLAS_CLASS, | ||
136 | .ids = ACPI_ATLAS_BUTTON_HID, | ||
137 | .ops = { | ||
138 | .add = atlas_acpi_button_add, | ||
139 | .remove = atlas_acpi_button_remove, | ||
140 | }, | ||
141 | }; | ||
142 | |||
143 | static int __init atlas_acpi_init(void) | ||
144 | { | ||
145 | int result; | ||
146 | |||
147 | if (acpi_disabled) | ||
148 | return -ENODEV; | ||
149 | |||
150 | result = acpi_bus_register_driver(&atlas_acpi_driver); | ||
151 | if (result < 0) { | ||
152 | printk(KERN_ERR "Atlas ACPI: Unable to register driver\n"); | ||
153 | return -ENODEV; | ||
154 | } | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static void __exit atlas_acpi_exit(void) | ||
160 | { | ||
161 | acpi_bus_unregister_driver(&atlas_acpi_driver); | ||
162 | } | ||
163 | |||
164 | module_init(atlas_acpi_init); | ||
165 | module_exit(atlas_acpi_exit); | ||
166 | |||
167 | MODULE_AUTHOR("Jaya Kumar"); | ||
168 | MODULE_LICENSE("GPL"); | ||
169 | MODULE_DESCRIPTION("Atlas button driver"); | ||
170 | |||
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 7b9d1c1da41a..e1183aeb8ed5 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -335,6 +335,17 @@ static struct key_entry keymap_aopen_1559as[] = { | |||
335 | { KE_END, 0 }, | 335 | { KE_END, 0 }, |
336 | }; | 336 | }; |
337 | 337 | ||
338 | static struct key_entry keymap_fs_amilo_d88x0[] = { | ||
339 | { KE_KEY, 0x01, KEY_HELP }, | ||
340 | { KE_KEY, 0x08, KEY_MUTE }, | ||
341 | { KE_KEY, 0x31, KEY_MAIL }, | ||
342 | { KE_KEY, 0x36, KEY_WWW }, | ||
343 | { KE_KEY, 0x11, KEY_PROG1 }, | ||
344 | { KE_KEY, 0x12, KEY_PROG2 }, | ||
345 | { KE_KEY, 0x13, KEY_PROG3 }, | ||
346 | { KE_END, 0 } | ||
347 | }; | ||
348 | |||
338 | /* | 349 | /* |
339 | * If your machine is not here (which is currently rather likely), please send | 350 | * If your machine is not here (which is currently rather likely), please send |
340 | * a list of buttons and their key codes (reported when loading this module | 351 | * a list of buttons and their key codes (reported when loading this module |
@@ -413,6 +424,15 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
413 | }, | 424 | }, |
414 | .driver_data = keymap_wistron_ms2111 | 425 | .driver_data = keymap_wistron_ms2111 |
415 | }, | 426 | }, |
427 | { | ||
428 | .callback = dmi_matched, | ||
429 | .ident = "Fujitsu Siemens Amilo D88x0", | ||
430 | .matches = { | ||
431 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
432 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO D"), | ||
433 | }, | ||
434 | .driver_data = keymap_fs_amilo_d88x0 | ||
435 | }, | ||
416 | { NULL, } | 436 | { NULL, } |
417 | }; | 437 | }; |
418 | 438 | ||
diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c index 13dd96785e39..701ebd5473cf 100644 --- a/drivers/input/mouse/inport.c +++ b/drivers/input/mouse/inport.c | |||
@@ -61,7 +61,7 @@ MODULE_LICENSE("GPL"); | |||
61 | #define INPORT_REG_MODE 0x07 | 61 | #define INPORT_REG_MODE 0x07 |
62 | #define INPORT_RESET 0x80 | 62 | #define INPORT_RESET 0x80 |
63 | 63 | ||
64 | #ifdef CONFIG_INPUT_ATIXL | 64 | #ifdef CONFIG_MOUSE_ATIXL |
65 | #define INPORT_NAME "ATI XL Mouse" | 65 | #define INPORT_NAME "ATI XL Mouse" |
66 | #define INPORT_VENDOR 0x0002 | 66 | #define INPORT_VENDOR 0x0002 |
67 | #define INPORT_SPEED_30HZ 0x01 | 67 | #define INPORT_SPEED_30HZ 0x01 |
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c index f155c1fea04e..05d992e514f0 100644 --- a/drivers/input/mouse/pc110pad.c +++ b/drivers/input/mouse/pc110pad.c | |||
@@ -113,7 +113,7 @@ static int __init pc110pad_init(void) | |||
113 | dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); | 113 | dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); |
114 | if (dev) { | 114 | if (dev) { |
115 | pci_dev_put(dev); | 115 | pci_dev_put(dev); |
116 | return -ENOENT; | 116 | return -ENODEV; |
117 | } | 117 | } |
118 | 118 | ||
119 | if (!request_region(pc110pad_io, 4, "pc110pad")) { | 119 | if (!request_region(pc110pad_io, 4, "pc110pad")) { |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index debe9445488c..c3fdfc1f342a 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -371,7 +371,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
371 | if (unlikely(i8042_suppress_kbd_ack)) | 371 | if (unlikely(i8042_suppress_kbd_ack)) |
372 | if (port_no == I8042_KBD_PORT_NO && | 372 | if (port_no == I8042_KBD_PORT_NO && |
373 | (data == 0xfa || data == 0xfe)) { | 373 | (data == 0xfa || data == 0xfe)) { |
374 | i8042_suppress_kbd_ack = 0; | 374 | i8042_suppress_kbd_ack--; |
375 | goto out; | 375 | goto out; |
376 | } | 376 | } |
377 | 377 | ||
@@ -543,6 +543,7 @@ static int __devinit i8042_check_aux(void) | |||
543 | { | 543 | { |
544 | int retval = -1; | 544 | int retval = -1; |
545 | int irq_registered = 0; | 545 | int irq_registered = 0; |
546 | int aux_loop_broken = 0; | ||
546 | unsigned long flags; | 547 | unsigned long flags; |
547 | unsigned char param; | 548 | unsigned char param; |
548 | 549 | ||
@@ -572,6 +573,8 @@ static int __devinit i8042_check_aux(void) | |||
572 | if (i8042_command(¶m, I8042_CMD_AUX_TEST) || | 573 | if (i8042_command(¶m, I8042_CMD_AUX_TEST) || |
573 | (param && param != 0xfa && param != 0xff)) | 574 | (param && param != 0xfa && param != 0xff)) |
574 | return -1; | 575 | return -1; |
576 | |||
577 | aux_loop_broken = 1; | ||
575 | } | 578 | } |
576 | 579 | ||
577 | /* | 580 | /* |
@@ -595,7 +598,7 @@ static int __devinit i8042_check_aux(void) | |||
595 | * used it for a PCI card or somethig else. | 598 | * used it for a PCI card or somethig else. |
596 | */ | 599 | */ |
597 | 600 | ||
598 | if (i8042_noloop) { | 601 | if (i8042_noloop || aux_loop_broken) { |
599 | /* | 602 | /* |
600 | * Without LOOP command we can't test AUX IRQ delivery. Assume the port | 603 | * Without LOOP command we can't test AUX IRQ delivery. Assume the port |
601 | * is working and hope we are right. | 604 | * is working and hope we are right. |
@@ -838,13 +841,14 @@ static long i8042_panic_blink(long count) | |||
838 | led ^= 0x01 | 0x04; | 841 | led ^= 0x01 | 0x04; |
839 | while (i8042_read_status() & I8042_STR_IBF) | 842 | while (i8042_read_status() & I8042_STR_IBF) |
840 | DELAY; | 843 | DELAY; |
841 | i8042_suppress_kbd_ack = 1; | 844 | dbg("%02x -> i8042 (panic blink)", 0xed); |
845 | i8042_suppress_kbd_ack = 2; | ||
842 | i8042_write_data(0xed); /* set leds */ | 846 | i8042_write_data(0xed); /* set leds */ |
843 | DELAY; | 847 | DELAY; |
844 | while (i8042_read_status() & I8042_STR_IBF) | 848 | while (i8042_read_status() & I8042_STR_IBF) |
845 | DELAY; | 849 | DELAY; |
846 | DELAY; | 850 | DELAY; |
847 | i8042_suppress_kbd_ack = 1; | 851 | dbg("%02x -> i8042 (panic blink)", led); |
848 | i8042_write_data(led); | 852 | i8042_write_data(led); |
849 | DELAY; | 853 | DELAY; |
850 | last_blink = count; | 854 | last_blink = count; |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 6b46c9bf1d20..971618059a6f 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -12,13 +12,18 @@ menuconfig INPUT_TOUCHSCREEN | |||
12 | if INPUT_TOUCHSCREEN | 12 | if INPUT_TOUCHSCREEN |
13 | 13 | ||
14 | config TOUCHSCREEN_ADS7846 | 14 | config TOUCHSCREEN_ADS7846 |
15 | tristate "ADS 7846 based touchscreens" | 15 | tristate "ADS 7846/7843 based touchscreens" |
16 | depends on SPI_MASTER | 16 | depends on SPI_MASTER |
17 | depends on HWMON = n || HWMON | ||
17 | help | 18 | help |
18 | Say Y here if you have a touchscreen interface using the | 19 | Say Y here if you have a touchscreen interface using the |
19 | ADS7846 controller, and your board-specific initialization | 20 | ADS7846 or ADS7843 controller, and your board-specific setup |
20 | code includes that in its table of SPI devices. | 21 | code includes that in its table of SPI devices. |
21 | 22 | ||
23 | If HWMON is selected, and the driver is told the reference voltage | ||
24 | on your board, you will also get hwmon interfaces for the voltage | ||
25 | (and on ads7846, temperature) sensors of this chip. | ||
26 | |||
22 | If unsure, say N (but it's safe to say "Y"). | 27 | If unsure, say N (but it's safe to say "Y"). |
23 | 28 | ||
24 | To compile this driver as a module, choose M here: the | 29 | To compile this driver as a module, choose M here: the |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index c6164b6f476a..cd251efda410 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -17,8 +17,9 @@ | |||
17 | * it under the terms of the GNU General Public License version 2 as | 17 | * it under the terms of the GNU General Public License version 2 as |
18 | * published by the Free Software Foundation. | 18 | * published by the Free Software Foundation. |
19 | */ | 19 | */ |
20 | #include <linux/device.h> | 20 | #include <linux/hwmon.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/err.h> | ||
22 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
23 | #include <linux/input.h> | 24 | #include <linux/input.h> |
24 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
@@ -54,7 +55,8 @@ | |||
54 | * files. | 55 | * files. |
55 | */ | 56 | */ |
56 | 57 | ||
57 | #define TS_POLL_PERIOD msecs_to_jiffies(10) | 58 | #define TS_POLL_DELAY (1 * 1000000) /* ns delay before the first sample */ |
59 | #define TS_POLL_PERIOD (5 * 1000000) /* ns delay between samples */ | ||
58 | 60 | ||
59 | /* this driver doesn't aim at the peak continuous sample rate */ | 61 | /* this driver doesn't aim at the peak continuous sample rate */ |
60 | #define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */) | 62 | #define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */) |
@@ -63,12 +65,12 @@ struct ts_event { | |||
63 | /* For portability, we can't read 12 bit values using SPI (which | 65 | /* For portability, we can't read 12 bit values using SPI (which |
64 | * would make the controller deliver them as native byteorder u16 | 66 | * would make the controller deliver them as native byteorder u16 |
65 | * with msbs zeroed). Instead, we read them as two 8-bit values, | 67 | * with msbs zeroed). Instead, we read them as two 8-bit values, |
66 | * which need byteswapping then range adjustment. | 68 | * *** WHICH NEED BYTESWAPPING *** and range adjustment. |
67 | */ | 69 | */ |
68 | __be16 x; | 70 | u16 x; |
69 | __be16 y; | 71 | u16 y; |
70 | __be16 z1, z2; | 72 | u16 z1, z2; |
71 | int ignore; | 73 | int ignore; |
72 | }; | 74 | }; |
73 | 75 | ||
74 | struct ads7846 { | 76 | struct ads7846 { |
@@ -76,7 +78,12 @@ struct ads7846 { | |||
76 | char phys[32]; | 78 | char phys[32]; |
77 | 79 | ||
78 | struct spi_device *spi; | 80 | struct spi_device *spi; |
81 | |||
82 | #if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE) | ||
79 | struct attribute_group *attr_group; | 83 | struct attribute_group *attr_group; |
84 | struct class_device *hwmon; | ||
85 | #endif | ||
86 | |||
80 | u16 model; | 87 | u16 model; |
81 | u16 vref_delay_usecs; | 88 | u16 vref_delay_usecs; |
82 | u16 x_plate_ohms; | 89 | u16 x_plate_ohms; |
@@ -99,13 +106,16 @@ struct ads7846 { | |||
99 | u16 debounce_rep; | 106 | u16 debounce_rep; |
100 | 107 | ||
101 | spinlock_t lock; | 108 | spinlock_t lock; |
102 | struct timer_list timer; /* P: lock */ | 109 | struct hrtimer timer; |
103 | unsigned pendown:1; /* P: lock */ | 110 | unsigned pendown:1; /* P: lock */ |
104 | unsigned pending:1; /* P: lock */ | 111 | unsigned pending:1; /* P: lock */ |
105 | // FIXME remove "irq_disabled" | 112 | // FIXME remove "irq_disabled" |
106 | unsigned irq_disabled:1; /* P: lock */ | 113 | unsigned irq_disabled:1; /* P: lock */ |
107 | unsigned disabled:1; | 114 | unsigned disabled:1; |
108 | 115 | ||
116 | int (*filter)(void *data, int data_idx, int *val); | ||
117 | void *filter_data; | ||
118 | void (*filter_cleanup)(void *data); | ||
109 | int (*get_pendown_state)(void); | 119 | int (*get_pendown_state)(void); |
110 | }; | 120 | }; |
111 | 121 | ||
@@ -142,15 +152,16 @@ struct ads7846 { | |||
142 | #define MAX_12BIT ((1<<12)-1) | 152 | #define MAX_12BIT ((1<<12)-1) |
143 | 153 | ||
144 | /* leave ADC powered up (disables penirq) between differential samples */ | 154 | /* leave ADC powered up (disables penirq) between differential samples */ |
145 | #define READ_12BIT_DFR(x) (ADS_START | ADS_A2A1A0_d_ ## x \ | 155 | #define READ_12BIT_DFR(x, adc, vref) (ADS_START | ADS_A2A1A0_d_ ## x \ |
146 | | ADS_12_BIT | ADS_DFR) | 156 | | ADS_12_BIT | ADS_DFR | \ |
157 | (adc ? ADS_PD10_ADC_ON : 0) | (vref ? ADS_PD10_REF_ON : 0)) | ||
147 | 158 | ||
148 | #define READ_Y (READ_12BIT_DFR(y) | ADS_PD10_ADC_ON) | 159 | #define READ_Y(vref) (READ_12BIT_DFR(y, 1, vref)) |
149 | #define READ_Z1 (READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON) | 160 | #define READ_Z1(vref) (READ_12BIT_DFR(z1, 1, vref)) |
150 | #define READ_Z2 (READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON) | 161 | #define READ_Z2(vref) (READ_12BIT_DFR(z2, 1, vref)) |
151 | 162 | ||
152 | #define READ_X (READ_12BIT_DFR(x) | ADS_PD10_ADC_ON) | 163 | #define READ_X(vref) (READ_12BIT_DFR(x, 1, vref)) |
153 | #define PWRDOWN (READ_12BIT_DFR(y) | ADS_PD10_PDOWN) /* LAST */ | 164 | #define PWRDOWN (READ_12BIT_DFR(y, 0, 0)) /* LAST */ |
154 | 165 | ||
155 | /* single-ended samples need to first power up reference voltage; | 166 | /* single-ended samples need to first power up reference voltage; |
156 | * we leave both ADC and VREF powered | 167 | * we leave both ADC and VREF powered |
@@ -158,14 +169,19 @@ struct ads7846 { | |||
158 | #define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \ | 169 | #define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \ |
159 | | ADS_12_BIT | ADS_SER) | 170 | | ADS_12_BIT | ADS_SER) |
160 | 171 | ||
161 | #define REF_ON (READ_12BIT_DFR(x) | ADS_PD10_ALL_ON) | 172 | #define REF_ON (READ_12BIT_DFR(x, 1, 1)) |
162 | #define REF_OFF (READ_12BIT_DFR(y) | ADS_PD10_PDOWN) | 173 | #define REF_OFF (READ_12BIT_DFR(y, 0, 0)) |
163 | 174 | ||
164 | /*--------------------------------------------------------------------------*/ | 175 | /*--------------------------------------------------------------------------*/ |
165 | 176 | ||
166 | /* | 177 | /* |
167 | * Non-touchscreen sensors only use single-ended conversions. | 178 | * Non-touchscreen sensors only use single-ended conversions. |
179 | * The range is GND..vREF. The ads7843 and ads7835 must use external vREF; | ||
180 | * ads7846 lets that pin be unconnected, to use internal vREF. | ||
168 | */ | 181 | */ |
182 | static unsigned vREF_mV; | ||
183 | module_param(vREF_mV, uint, 0); | ||
184 | MODULE_PARM_DESC(vREF_mV, "external vREF voltage, in milliVolts"); | ||
169 | 185 | ||
170 | struct ser_req { | 186 | struct ser_req { |
171 | u8 ref_on; | 187 | u8 ref_on; |
@@ -193,50 +209,55 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) | |||
193 | struct ser_req *req = kzalloc(sizeof *req, GFP_KERNEL); | 209 | struct ser_req *req = kzalloc(sizeof *req, GFP_KERNEL); |
194 | int status; | 210 | int status; |
195 | int sample; | 211 | int sample; |
196 | int i; | 212 | int use_internal; |
197 | 213 | ||
198 | if (!req) | 214 | if (!req) |
199 | return -ENOMEM; | 215 | return -ENOMEM; |
200 | 216 | ||
201 | spi_message_init(&req->msg); | 217 | spi_message_init(&req->msg); |
202 | 218 | ||
203 | /* activate reference, so it has time to settle; */ | 219 | /* FIXME boards with ads7846 might use external vref instead ... */ |
204 | req->ref_on = REF_ON; | 220 | use_internal = (ts->model == 7846); |
205 | req->xfer[0].tx_buf = &req->ref_on; | 221 | |
206 | req->xfer[0].len = 1; | 222 | /* maybe turn on internal vREF, and let it settle */ |
207 | req->xfer[1].rx_buf = &req->scratch; | 223 | if (use_internal) { |
208 | req->xfer[1].len = 2; | 224 | req->ref_on = REF_ON; |
209 | 225 | req->xfer[0].tx_buf = &req->ref_on; | |
210 | /* | 226 | req->xfer[0].len = 1; |
211 | * for external VREF, 0 usec (and assume it's always on); | 227 | spi_message_add_tail(&req->xfer[0], &req->msg); |
212 | * for 1uF, use 800 usec; | 228 | |
213 | * no cap, 100 usec. | 229 | req->xfer[1].rx_buf = &req->scratch; |
214 | */ | 230 | req->xfer[1].len = 2; |
215 | req->xfer[1].delay_usecs = ts->vref_delay_usecs; | 231 | |
232 | /* for 1uF, settle for 800 usec; no cap, 100 usec. */ | ||
233 | req->xfer[1].delay_usecs = ts->vref_delay_usecs; | ||
234 | spi_message_add_tail(&req->xfer[1], &req->msg); | ||
235 | } | ||
216 | 236 | ||
217 | /* take sample */ | 237 | /* take sample */ |
218 | req->command = (u8) command; | 238 | req->command = (u8) command; |
219 | req->xfer[2].tx_buf = &req->command; | 239 | req->xfer[2].tx_buf = &req->command; |
220 | req->xfer[2].len = 1; | 240 | req->xfer[2].len = 1; |
241 | spi_message_add_tail(&req->xfer[2], &req->msg); | ||
242 | |||
221 | req->xfer[3].rx_buf = &req->sample; | 243 | req->xfer[3].rx_buf = &req->sample; |
222 | req->xfer[3].len = 2; | 244 | req->xfer[3].len = 2; |
245 | spi_message_add_tail(&req->xfer[3], &req->msg); | ||
223 | 246 | ||
224 | /* REVISIT: take a few more samples, and compare ... */ | 247 | /* REVISIT: take a few more samples, and compare ... */ |
225 | 248 | ||
226 | /* turn off reference */ | 249 | /* maybe off internal vREF */ |
227 | req->ref_off = REF_OFF; | 250 | if (use_internal) { |
228 | req->xfer[4].tx_buf = &req->ref_off; | 251 | req->ref_off = REF_OFF; |
229 | req->xfer[4].len = 1; | 252 | req->xfer[4].tx_buf = &req->ref_off; |
230 | req->xfer[5].rx_buf = &req->scratch; | 253 | req->xfer[4].len = 1; |
231 | req->xfer[5].len = 2; | 254 | spi_message_add_tail(&req->xfer[4], &req->msg); |
232 | 255 | ||
233 | CS_CHANGE(req->xfer[5]); | 256 | req->xfer[5].rx_buf = &req->scratch; |
234 | 257 | req->xfer[5].len = 2; | |
235 | /* group all the transfers together, so we can't interfere with | 258 | CS_CHANGE(req->xfer[5]); |
236 | * reading touchscreen state; disable penirq while sampling | 259 | spi_message_add_tail(&req->xfer[5], &req->msg); |
237 | */ | 260 | } |
238 | for (i = 0; i < 6; i++) | ||
239 | spi_message_add_tail(&req->xfer[i], &req->msg); | ||
240 | 261 | ||
241 | ts->irq_disabled = 1; | 262 | ts->irq_disabled = 1; |
242 | disable_irq(spi->irq); | 263 | disable_irq(spi->irq); |
@@ -256,25 +277,173 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) | |||
256 | return status ? status : sample; | 277 | return status ? status : sample; |
257 | } | 278 | } |
258 | 279 | ||
259 | #define SHOW(name) static ssize_t \ | 280 | #if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE) |
281 | |||
282 | #define SHOW(name, var, adjust) static ssize_t \ | ||
260 | name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ | 283 | name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ |
261 | { \ | 284 | { \ |
285 | struct ads7846 *ts = dev_get_drvdata(dev); \ | ||
262 | ssize_t v = ads7846_read12_ser(dev, \ | 286 | ssize_t v = ads7846_read12_ser(dev, \ |
263 | READ_12BIT_SER(name) | ADS_PD10_ALL_ON); \ | 287 | READ_12BIT_SER(var) | ADS_PD10_ALL_ON); \ |
264 | if (v < 0) \ | 288 | if (v < 0) \ |
265 | return v; \ | 289 | return v; \ |
266 | return sprintf(buf, "%u\n", (unsigned) v); \ | 290 | return sprintf(buf, "%u\n", adjust(ts, v)); \ |
267 | } \ | 291 | } \ |
268 | static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL); | 292 | static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL); |
269 | 293 | ||
270 | SHOW(temp0) | 294 | |
271 | SHOW(temp1) | 295 | /* Sysfs conventions report temperatures in millidegrees Celcius. |
272 | SHOW(vaux) | 296 | * ADS7846 could use the low-accuracy two-sample scheme, but can't do the high |
273 | SHOW(vbatt) | 297 | * accuracy scheme without calibration data. For now we won't try either; |
298 | * userspace sees raw sensor values, and must scale/calibrate appropriately. | ||
299 | */ | ||
300 | static inline unsigned null_adjust(struct ads7846 *ts, ssize_t v) | ||
301 | { | ||
302 | return v; | ||
303 | } | ||
304 | |||
305 | SHOW(temp0, temp0, null_adjust) /* temp1_input */ | ||
306 | SHOW(temp1, temp1, null_adjust) /* temp2_input */ | ||
307 | |||
308 | |||
309 | /* sysfs conventions report voltages in millivolts. We can convert voltages | ||
310 | * if we know vREF. userspace may need to scale vAUX to match the board's | ||
311 | * external resistors; we assume that vBATT only uses the internal ones. | ||
312 | */ | ||
313 | static inline unsigned vaux_adjust(struct ads7846 *ts, ssize_t v) | ||
314 | { | ||
315 | unsigned retval = v; | ||
316 | |||
317 | /* external resistors may scale vAUX into 0..vREF */ | ||
318 | retval *= vREF_mV; | ||
319 | retval = retval >> 12; | ||
320 | return retval; | ||
321 | } | ||
322 | |||
323 | static inline unsigned vbatt_adjust(struct ads7846 *ts, ssize_t v) | ||
324 | { | ||
325 | unsigned retval = vaux_adjust(ts, v); | ||
326 | |||
327 | /* ads7846 has a resistor ladder to scale this signal down */ | ||
328 | if (ts->model == 7846) | ||
329 | retval *= 4; | ||
330 | return retval; | ||
331 | } | ||
332 | |||
333 | SHOW(in0_input, vaux, vaux_adjust) | ||
334 | SHOW(in1_input, vbatt, vbatt_adjust) | ||
335 | |||
336 | |||
337 | static struct attribute *ads7846_attributes[] = { | ||
338 | &dev_attr_temp0.attr, | ||
339 | &dev_attr_temp1.attr, | ||
340 | &dev_attr_in0_input.attr, | ||
341 | &dev_attr_in1_input.attr, | ||
342 | NULL, | ||
343 | }; | ||
344 | |||
345 | static struct attribute_group ads7846_attr_group = { | ||
346 | .attrs = ads7846_attributes, | ||
347 | }; | ||
348 | |||
349 | static struct attribute *ads7843_attributes[] = { | ||
350 | &dev_attr_in0_input.attr, | ||
351 | &dev_attr_in1_input.attr, | ||
352 | NULL, | ||
353 | }; | ||
354 | |||
355 | static struct attribute_group ads7843_attr_group = { | ||
356 | .attrs = ads7843_attributes, | ||
357 | }; | ||
358 | |||
359 | static struct attribute *ads7845_attributes[] = { | ||
360 | &dev_attr_in0_input.attr, | ||
361 | NULL, | ||
362 | }; | ||
363 | |||
364 | static struct attribute_group ads7845_attr_group = { | ||
365 | .attrs = ads7845_attributes, | ||
366 | }; | ||
367 | |||
368 | static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts) | ||
369 | { | ||
370 | struct class_device *hwmon; | ||
371 | int err; | ||
372 | |||
373 | /* hwmon sensors need a reference voltage */ | ||
374 | switch (ts->model) { | ||
375 | case 7846: | ||
376 | if (!vREF_mV) { | ||
377 | dev_dbg(&spi->dev, "assuming 2.5V internal vREF\n"); | ||
378 | vREF_mV = 2500; | ||
379 | } | ||
380 | break; | ||
381 | case 7845: | ||
382 | case 7843: | ||
383 | if (!vREF_mV) { | ||
384 | dev_warn(&spi->dev, | ||
385 | "external vREF for ADS%d not specified\n", | ||
386 | ts->model); | ||
387 | return 0; | ||
388 | } | ||
389 | break; | ||
390 | } | ||
391 | |||
392 | /* different chips have different sensor groups */ | ||
393 | switch (ts->model) { | ||
394 | case 7846: | ||
395 | ts->attr_group = &ads7846_attr_group; | ||
396 | break; | ||
397 | case 7845: | ||
398 | ts->attr_group = &ads7845_attr_group; | ||
399 | break; | ||
400 | case 7843: | ||
401 | ts->attr_group = &ads7843_attr_group; | ||
402 | break; | ||
403 | default: | ||
404 | dev_dbg(&spi->dev, "ADS%d not recognized\n", ts->model); | ||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | err = sysfs_create_group(&spi->dev.kobj, ts->attr_group); | ||
409 | if (err) | ||
410 | return err; | ||
411 | |||
412 | hwmon = hwmon_device_register(&spi->dev); | ||
413 | if (IS_ERR(hwmon)) { | ||
414 | sysfs_remove_group(&spi->dev.kobj, ts->attr_group); | ||
415 | return PTR_ERR(hwmon); | ||
416 | } | ||
417 | |||
418 | ts->hwmon = hwmon; | ||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static void ads784x_hwmon_unregister(struct spi_device *spi, | ||
423 | struct ads7846 *ts) | ||
424 | { | ||
425 | if (ts->hwmon) { | ||
426 | sysfs_remove_group(&spi->dev.kobj, ts->attr_group); | ||
427 | hwmon_device_unregister(ts->hwmon); | ||
428 | } | ||
429 | } | ||
430 | |||
431 | #else | ||
432 | static inline int ads784x_hwmon_register(struct spi_device *spi, | ||
433 | struct ads7846 *ts) | ||
434 | { | ||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | static inline void ads784x_hwmon_unregister(struct spi_device *spi, | ||
439 | struct ads7846 *ts) | ||
440 | { | ||
441 | } | ||
442 | #endif | ||
274 | 443 | ||
275 | static int is_pen_down(struct device *dev) | 444 | static int is_pen_down(struct device *dev) |
276 | { | 445 | { |
277 | struct ads7846 *ts = dev_get_drvdata(dev); | 446 | struct ads7846 *ts = dev_get_drvdata(dev); |
278 | 447 | ||
279 | return ts->pendown; | 448 | return ts->pendown; |
280 | } | 449 | } |
@@ -318,46 +487,14 @@ static ssize_t ads7846_disable_store(struct device *dev, | |||
318 | 487 | ||
319 | static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store); | 488 | static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store); |
320 | 489 | ||
321 | static struct attribute *ads7846_attributes[] = { | 490 | static struct attribute *ads784x_attributes[] = { |
322 | &dev_attr_temp0.attr, | ||
323 | &dev_attr_temp1.attr, | ||
324 | &dev_attr_vbatt.attr, | ||
325 | &dev_attr_vaux.attr, | ||
326 | &dev_attr_pen_down.attr, | ||
327 | &dev_attr_disable.attr, | ||
328 | NULL, | ||
329 | }; | ||
330 | |||
331 | static struct attribute_group ads7846_attr_group = { | ||
332 | .attrs = ads7846_attributes, | ||
333 | }; | ||
334 | |||
335 | /* | ||
336 | * ads7843/7845 don't have temperature sensors, and | ||
337 | * use the other sensors a bit differently too | ||
338 | */ | ||
339 | |||
340 | static struct attribute *ads7843_attributes[] = { | ||
341 | &dev_attr_vbatt.attr, | ||
342 | &dev_attr_vaux.attr, | ||
343 | &dev_attr_pen_down.attr, | 491 | &dev_attr_pen_down.attr, |
344 | &dev_attr_disable.attr, | 492 | &dev_attr_disable.attr, |
345 | NULL, | 493 | NULL, |
346 | }; | 494 | }; |
347 | 495 | ||
348 | static struct attribute_group ads7843_attr_group = { | 496 | static struct attribute_group ads784x_attr_group = { |
349 | .attrs = ads7843_attributes, | 497 | .attrs = ads784x_attributes, |
350 | }; | ||
351 | |||
352 | static struct attribute *ads7845_attributes[] = { | ||
353 | &dev_attr_vaux.attr, | ||
354 | &dev_attr_pen_down.attr, | ||
355 | &dev_attr_disable.attr, | ||
356 | NULL, | ||
357 | }; | ||
358 | |||
359 | static struct attribute_group ads7845_attr_group = { | ||
360 | .attrs = ads7845_attributes, | ||
361 | }; | 498 | }; |
362 | 499 | ||
363 | /*--------------------------------------------------------------------------*/ | 500 | /*--------------------------------------------------------------------------*/ |
@@ -373,25 +510,22 @@ static struct attribute_group ads7845_attr_group = { | |||
373 | static void ads7846_rx(void *ads) | 510 | static void ads7846_rx(void *ads) |
374 | { | 511 | { |
375 | struct ads7846 *ts = ads; | 512 | struct ads7846 *ts = ads; |
376 | struct input_dev *input_dev = ts->input; | ||
377 | unsigned Rt; | 513 | unsigned Rt; |
378 | unsigned sync = 0; | ||
379 | u16 x, y, z1, z2; | 514 | u16 x, y, z1, z2; |
380 | unsigned long flags; | ||
381 | 515 | ||
382 | /* adjust: on-wire is a must-ignore bit, a BE12 value, then padding; | 516 | /* ads7846_rx_val() did in-place conversion (including byteswap) from |
383 | * built from two 8 bit values written msb-first. | 517 | * on-the-wire format as part of debouncing to get stable readings. |
384 | */ | 518 | */ |
385 | x = (be16_to_cpu(ts->tc.x) >> 3) & 0x0fff; | 519 | x = ts->tc.x; |
386 | y = (be16_to_cpu(ts->tc.y) >> 3) & 0x0fff; | 520 | y = ts->tc.y; |
387 | z1 = (be16_to_cpu(ts->tc.z1) >> 3) & 0x0fff; | 521 | z1 = ts->tc.z1; |
388 | z2 = (be16_to_cpu(ts->tc.z2) >> 3) & 0x0fff; | 522 | z2 = ts->tc.z2; |
389 | 523 | ||
390 | /* range filtering */ | 524 | /* range filtering */ |
391 | if (x == MAX_12BIT) | 525 | if (x == MAX_12BIT) |
392 | x = 0; | 526 | x = 0; |
393 | 527 | ||
394 | if (likely(x && z1 && !device_suspended(&ts->spi->dev))) { | 528 | if (likely(x && z1)) { |
395 | /* compute touch pressure resistance using equation #2 */ | 529 | /* compute touch pressure resistance using equation #2 */ |
396 | Rt = z2; | 530 | Rt = z2; |
397 | Rt -= z1; | 531 | Rt -= z1; |
@@ -403,100 +537,129 @@ static void ads7846_rx(void *ads) | |||
403 | Rt = 0; | 537 | Rt = 0; |
404 | 538 | ||
405 | /* Sample found inconsistent by debouncing or pressure is beyond | 539 | /* Sample found inconsistent by debouncing or pressure is beyond |
406 | * the maximum. Don't report it to user space, repeat at least | 540 | * the maximum. Don't report it to user space, repeat at least |
407 | * once more the measurement */ | 541 | * once more the measurement |
542 | */ | ||
408 | if (ts->tc.ignore || Rt > ts->pressure_max) { | 543 | if (ts->tc.ignore || Rt > ts->pressure_max) { |
409 | mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); | 544 | #ifdef VERBOSE |
545 | pr_debug("%s: ignored %d pressure %d\n", | ||
546 | ts->spi->dev.bus_id, ts->tc.ignore, Rt); | ||
547 | #endif | ||
548 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | ||
549 | HRTIMER_REL); | ||
410 | return; | 550 | return; |
411 | } | 551 | } |
412 | 552 | ||
413 | /* NOTE: "pendown" is inferred from pressure; we don't rely on | 553 | /* NOTE: We can't rely on the pressure to determine the pen down |
414 | * being able to check nPENIRQ status, or "friendly" trigger modes | 554 | * state, even this controller has a pressure sensor. The pressure |
415 | * (both-edges is much better than just-falling or low-level). | 555 | * value can fluctuate for quite a while after lifting the pen and |
556 | * in some cases may not even settle at the expected value. | ||
416 | * | 557 | * |
417 | * REVISIT: some boards may require reading nPENIRQ; it's | 558 | * The only safe way to check for the pen up condition is in the |
418 | * needed on 7843. and 7845 reads pressure differently... | 559 | * timer by reading the pen signal state (it's a GPIO _and_ IRQ). |
419 | * | ||
420 | * REVISIT: the touchscreen might not be connected; this code | ||
421 | * won't notice that, even if nPENIRQ never fires ... | ||
422 | */ | 560 | */ |
423 | if (!ts->pendown && Rt != 0) { | ||
424 | input_report_key(input_dev, BTN_TOUCH, 1); | ||
425 | sync = 1; | ||
426 | } else if (ts->pendown && Rt == 0) { | ||
427 | input_report_key(input_dev, BTN_TOUCH, 0); | ||
428 | sync = 1; | ||
429 | } | ||
430 | |||
431 | if (Rt) { | 561 | if (Rt) { |
432 | input_report_abs(input_dev, ABS_X, x); | 562 | struct input_dev *input = ts->input; |
433 | input_report_abs(input_dev, ABS_Y, y); | ||
434 | sync = 1; | ||
435 | } | ||
436 | |||
437 | if (sync) { | ||
438 | input_report_abs(input_dev, ABS_PRESSURE, Rt); | ||
439 | input_sync(input_dev); | ||
440 | } | ||
441 | 563 | ||
442 | #ifdef VERBOSE | 564 | if (!ts->pendown) { |
443 | if (Rt || ts->pendown) | 565 | input_report_key(input, BTN_TOUCH, 1); |
444 | pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id, | 566 | ts->pendown = 1; |
445 | x, y, Rt, Rt ? "" : " UP"); | 567 | #ifdef VERBOSE |
568 | dev_dbg(&ts->spi->dev, "DOWN\n"); | ||
446 | #endif | 569 | #endif |
570 | } | ||
571 | input_report_abs(input, ABS_X, x); | ||
572 | input_report_abs(input, ABS_Y, y); | ||
573 | input_report_abs(input, ABS_PRESSURE, Rt); | ||
447 | 574 | ||
448 | spin_lock_irqsave(&ts->lock, flags); | 575 | input_sync(input); |
449 | 576 | #ifdef VERBOSE | |
450 | ts->pendown = (Rt != 0); | 577 | dev_dbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt); |
451 | mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); | 578 | #endif |
579 | } | ||
452 | 580 | ||
453 | spin_unlock_irqrestore(&ts->lock, flags); | 581 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), HRTIMER_REL); |
454 | } | 582 | } |
455 | 583 | ||
456 | static void ads7846_debounce(void *ads) | 584 | static int ads7846_debounce(void *ads, int data_idx, int *val) |
457 | { | 585 | { |
458 | struct ads7846 *ts = ads; | 586 | struct ads7846 *ts = ads; |
459 | struct spi_message *m; | ||
460 | struct spi_transfer *t; | ||
461 | int val; | ||
462 | int status; | ||
463 | 587 | ||
464 | m = &ts->msg[ts->msg_idx]; | 588 | if (!ts->read_cnt || (abs(ts->last_read - *val) > ts->debounce_tol)) { |
465 | t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); | 589 | /* Start over collecting consistent readings. */ |
466 | val = (be16_to_cpu(*(__be16 *)t->rx_buf) >> 3) & 0x0fff; | 590 | ts->read_rep = 0; |
467 | if (!ts->read_cnt || (abs(ts->last_read - val) > ts->debounce_tol)) { | ||
468 | /* Repeat it, if this was the first read or the read | 591 | /* Repeat it, if this was the first read or the read |
469 | * wasn't consistent enough. */ | 592 | * wasn't consistent enough. */ |
470 | if (ts->read_cnt < ts->debounce_max) { | 593 | if (ts->read_cnt < ts->debounce_max) { |
471 | ts->last_read = val; | 594 | ts->last_read = *val; |
472 | ts->read_cnt++; | 595 | ts->read_cnt++; |
596 | return ADS7846_FILTER_REPEAT; | ||
473 | } else { | 597 | } else { |
474 | /* Maximum number of debouncing reached and still | 598 | /* Maximum number of debouncing reached and still |
475 | * not enough number of consistent readings. Abort | 599 | * not enough number of consistent readings. Abort |
476 | * the whole sample, repeat it in the next sampling | 600 | * the whole sample, repeat it in the next sampling |
477 | * period. | 601 | * period. |
478 | */ | 602 | */ |
479 | ts->tc.ignore = 1; | ||
480 | ts->read_cnt = 0; | 603 | ts->read_cnt = 0; |
481 | /* Last message will contain ads7846_rx() as the | 604 | return ADS7846_FILTER_IGNORE; |
482 | * completion function. | ||
483 | */ | ||
484 | m = ts->last_msg; | ||
485 | } | 605 | } |
486 | /* Start over collecting consistent readings. */ | ||
487 | ts->read_rep = 0; | ||
488 | } else { | 606 | } else { |
489 | if (++ts->read_rep > ts->debounce_rep) { | 607 | if (++ts->read_rep > ts->debounce_rep) { |
490 | /* Got a good reading for this coordinate, | 608 | /* Got a good reading for this coordinate, |
491 | * go for the next one. */ | 609 | * go for the next one. */ |
492 | ts->tc.ignore = 0; | ||
493 | ts->msg_idx++; | ||
494 | ts->read_cnt = 0; | 610 | ts->read_cnt = 0; |
495 | ts->read_rep = 0; | 611 | ts->read_rep = 0; |
496 | m++; | 612 | return ADS7846_FILTER_OK; |
497 | } else | 613 | } else { |
498 | /* Read more values that are consistent. */ | 614 | /* Read more values that are consistent. */ |
499 | ts->read_cnt++; | 615 | ts->read_cnt++; |
616 | return ADS7846_FILTER_REPEAT; | ||
617 | } | ||
618 | } | ||
619 | } | ||
620 | |||
621 | static int ads7846_no_filter(void *ads, int data_idx, int *val) | ||
622 | { | ||
623 | return ADS7846_FILTER_OK; | ||
624 | } | ||
625 | |||
626 | static void ads7846_rx_val(void *ads) | ||
627 | { | ||
628 | struct ads7846 *ts = ads; | ||
629 | struct spi_message *m; | ||
630 | struct spi_transfer *t; | ||
631 | u16 *rx_val; | ||
632 | int val; | ||
633 | int action; | ||
634 | int status; | ||
635 | |||
636 | m = &ts->msg[ts->msg_idx]; | ||
637 | t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); | ||
638 | rx_val = t->rx_buf; | ||
639 | |||
640 | /* adjust: on-wire is a must-ignore bit, a BE12 value, then padding; | ||
641 | * built from two 8 bit values written msb-first. | ||
642 | */ | ||
643 | val = be16_to_cpu(*rx_val) >> 3; | ||
644 | |||
645 | action = ts->filter(ts->filter_data, ts->msg_idx, &val); | ||
646 | switch (action) { | ||
647 | case ADS7846_FILTER_REPEAT: | ||
648 | break; | ||
649 | case ADS7846_FILTER_IGNORE: | ||
650 | ts->tc.ignore = 1; | ||
651 | /* Last message will contain ads7846_rx() as the | ||
652 | * completion function. | ||
653 | */ | ||
654 | m = ts->last_msg; | ||
655 | break; | ||
656 | case ADS7846_FILTER_OK: | ||
657 | *rx_val = val; | ||
658 | ts->tc.ignore = 0; | ||
659 | m = &ts->msg[++ts->msg_idx]; | ||
660 | break; | ||
661 | default: | ||
662 | BUG(); | ||
500 | } | 663 | } |
501 | status = spi_async(ts->spi, m); | 664 | status = spi_async(ts->spi, m); |
502 | if (status) | 665 | if (status) |
@@ -504,21 +667,34 @@ static void ads7846_debounce(void *ads) | |||
504 | status); | 667 | status); |
505 | } | 668 | } |
506 | 669 | ||
507 | static void ads7846_timer(unsigned long handle) | 670 | static int ads7846_timer(struct hrtimer *handle) |
508 | { | 671 | { |
509 | struct ads7846 *ts = (void *)handle; | 672 | struct ads7846 *ts = container_of(handle, struct ads7846, timer); |
510 | int status = 0; | 673 | int status = 0; |
511 | 674 | ||
512 | spin_lock_irq(&ts->lock); | 675 | spin_lock_irq(&ts->lock); |
513 | 676 | ||
514 | if (unlikely(ts->msg_idx && !ts->pendown)) { | 677 | if (unlikely(!ts->get_pendown_state() || |
678 | device_suspended(&ts->spi->dev))) { | ||
679 | if (ts->pendown) { | ||
680 | struct input_dev *input = ts->input; | ||
681 | |||
682 | input_report_key(input, BTN_TOUCH, 0); | ||
683 | input_report_abs(input, ABS_PRESSURE, 0); | ||
684 | input_sync(input); | ||
685 | |||
686 | ts->pendown = 0; | ||
687 | #ifdef VERBOSE | ||
688 | dev_dbg(&ts->spi->dev, "UP\n"); | ||
689 | #endif | ||
690 | } | ||
691 | |||
515 | /* measurement cycle ended */ | 692 | /* measurement cycle ended */ |
516 | if (!device_suspended(&ts->spi->dev)) { | 693 | if (!device_suspended(&ts->spi->dev)) { |
517 | ts->irq_disabled = 0; | 694 | ts->irq_disabled = 0; |
518 | enable_irq(ts->spi->irq); | 695 | enable_irq(ts->spi->irq); |
519 | } | 696 | } |
520 | ts->pending = 0; | 697 | ts->pending = 0; |
521 | ts->msg_idx = 0; | ||
522 | } else { | 698 | } else { |
523 | /* pen is still down, continue with the measurement */ | 699 | /* pen is still down, continue with the measurement */ |
524 | ts->msg_idx = 0; | 700 | ts->msg_idx = 0; |
@@ -528,6 +704,7 @@ static void ads7846_timer(unsigned long handle) | |||
528 | } | 704 | } |
529 | 705 | ||
530 | spin_unlock_irq(&ts->lock); | 706 | spin_unlock_irq(&ts->lock); |
707 | return HRTIMER_NORESTART; | ||
531 | } | 708 | } |
532 | 709 | ||
533 | static irqreturn_t ads7846_irq(int irq, void *handle) | 710 | static irqreturn_t ads7846_irq(int irq, void *handle) |
@@ -546,7 +723,8 @@ static irqreturn_t ads7846_irq(int irq, void *handle) | |||
546 | ts->irq_disabled = 1; | 723 | ts->irq_disabled = 1; |
547 | disable_irq(ts->spi->irq); | 724 | disable_irq(ts->spi->irq); |
548 | ts->pending = 1; | 725 | ts->pending = 1; |
549 | mod_timer(&ts->timer, jiffies); | 726 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), |
727 | HRTIMER_REL); | ||
550 | } | 728 | } |
551 | } | 729 | } |
552 | spin_unlock_irqrestore(&ts->lock, flags); | 730 | spin_unlock_irqrestore(&ts->lock, flags); |
@@ -632,6 +810,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
632 | struct ads7846_platform_data *pdata = spi->dev.platform_data; | 810 | struct ads7846_platform_data *pdata = spi->dev.platform_data; |
633 | struct spi_message *m; | 811 | struct spi_message *m; |
634 | struct spi_transfer *x; | 812 | struct spi_transfer *x; |
813 | int vref; | ||
635 | int err; | 814 | int err; |
636 | 815 | ||
637 | if (!spi->irq) { | 816 | if (!spi->irq) { |
@@ -665,6 +844,10 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
665 | * may not. So we stick to very-portable 8 bit words, both RX and TX. | 844 | * may not. So we stick to very-portable 8 bit words, both RX and TX. |
666 | */ | 845 | */ |
667 | spi->bits_per_word = 8; | 846 | spi->bits_per_word = 8; |
847 | spi->mode = SPI_MODE_1; | ||
848 | err = spi_setup(spi); | ||
849 | if (err < 0) | ||
850 | return err; | ||
668 | 851 | ||
669 | ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); | 852 | ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); |
670 | input_dev = input_allocate_device(); | 853 | input_dev = input_allocate_device(); |
@@ -679,8 +862,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
679 | ts->spi = spi; | 862 | ts->spi = spi; |
680 | ts->input = input_dev; | 863 | ts->input = input_dev; |
681 | 864 | ||
682 | init_timer(&ts->timer); | 865 | hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_REL); |
683 | ts->timer.data = (unsigned long) ts; | ||
684 | ts->timer.function = ads7846_timer; | 866 | ts->timer.function = ads7846_timer; |
685 | 867 | ||
686 | spin_lock_init(&ts->lock); | 868 | spin_lock_init(&ts->lock); |
@@ -689,14 +871,25 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
689 | ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; | 871 | ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; |
690 | ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; | 872 | ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; |
691 | ts->pressure_max = pdata->pressure_max ? : ~0; | 873 | ts->pressure_max = pdata->pressure_max ? : ~0; |
692 | if (pdata->debounce_max) { | 874 | |
875 | if (pdata->filter != NULL) { | ||
876 | if (pdata->filter_init != NULL) { | ||
877 | err = pdata->filter_init(pdata, &ts->filter_data); | ||
878 | if (err < 0) | ||
879 | goto err_free_mem; | ||
880 | } | ||
881 | ts->filter = pdata->filter; | ||
882 | ts->filter_cleanup = pdata->filter_cleanup; | ||
883 | } else if (pdata->debounce_max) { | ||
693 | ts->debounce_max = pdata->debounce_max; | 884 | ts->debounce_max = pdata->debounce_max; |
885 | if (ts->debounce_max < 2) | ||
886 | ts->debounce_max = 2; | ||
694 | ts->debounce_tol = pdata->debounce_tol; | 887 | ts->debounce_tol = pdata->debounce_tol; |
695 | ts->debounce_rep = pdata->debounce_rep; | 888 | ts->debounce_rep = pdata->debounce_rep; |
696 | if (ts->debounce_rep > ts->debounce_max + 1) | 889 | ts->filter = ads7846_debounce; |
697 | ts->debounce_rep = ts->debounce_max - 1; | 890 | ts->filter_data = ts; |
698 | } else | 891 | } else |
699 | ts->debounce_tol = ~0; | 892 | ts->filter = ads7846_no_filter; |
700 | ts->get_pendown_state = pdata->get_pendown_state; | 893 | ts->get_pendown_state = pdata->get_pendown_state; |
701 | 894 | ||
702 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); | 895 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); |
@@ -718,6 +911,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
718 | input_set_abs_params(input_dev, ABS_PRESSURE, | 911 | input_set_abs_params(input_dev, ABS_PRESSURE, |
719 | pdata->pressure_min, pdata->pressure_max, 0, 0); | 912 | pdata->pressure_min, pdata->pressure_max, 0, 0); |
720 | 913 | ||
914 | vref = pdata->keep_vref_on; | ||
915 | |||
721 | /* set up the transfers to read touchscreen state; this assumes we | 916 | /* set up the transfers to read touchscreen state; this assumes we |
722 | * use formula #2 for pressure, not #3. | 917 | * use formula #2 for pressure, not #3. |
723 | */ | 918 | */ |
@@ -727,7 +922,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
727 | spi_message_init(m); | 922 | spi_message_init(m); |
728 | 923 | ||
729 | /* y- still on; turn on only y+ (and ADC) */ | 924 | /* y- still on; turn on only y+ (and ADC) */ |
730 | ts->read_y = READ_Y; | 925 | ts->read_y = READ_Y(vref); |
731 | x->tx_buf = &ts->read_y; | 926 | x->tx_buf = &ts->read_y; |
732 | x->len = 1; | 927 | x->len = 1; |
733 | spi_message_add_tail(x, m); | 928 | spi_message_add_tail(x, m); |
@@ -737,7 +932,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
737 | x->len = 2; | 932 | x->len = 2; |
738 | spi_message_add_tail(x, m); | 933 | spi_message_add_tail(x, m); |
739 | 934 | ||
740 | m->complete = ads7846_debounce; | 935 | m->complete = ads7846_rx_val; |
741 | m->context = ts; | 936 | m->context = ts; |
742 | 937 | ||
743 | m++; | 938 | m++; |
@@ -745,7 +940,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
745 | 940 | ||
746 | /* turn y- off, x+ on, then leave in lowpower */ | 941 | /* turn y- off, x+ on, then leave in lowpower */ |
747 | x++; | 942 | x++; |
748 | ts->read_x = READ_X; | 943 | ts->read_x = READ_X(vref); |
749 | x->tx_buf = &ts->read_x; | 944 | x->tx_buf = &ts->read_x; |
750 | x->len = 1; | 945 | x->len = 1; |
751 | spi_message_add_tail(x, m); | 946 | spi_message_add_tail(x, m); |
@@ -755,7 +950,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
755 | x->len = 2; | 950 | x->len = 2; |
756 | spi_message_add_tail(x, m); | 951 | spi_message_add_tail(x, m); |
757 | 952 | ||
758 | m->complete = ads7846_debounce; | 953 | m->complete = ads7846_rx_val; |
759 | m->context = ts; | 954 | m->context = ts; |
760 | 955 | ||
761 | /* turn y+ off, x- on; we'll use formula #2 */ | 956 | /* turn y+ off, x- on; we'll use formula #2 */ |
@@ -764,7 +959,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
764 | spi_message_init(m); | 959 | spi_message_init(m); |
765 | 960 | ||
766 | x++; | 961 | x++; |
767 | ts->read_z1 = READ_Z1; | 962 | ts->read_z1 = READ_Z1(vref); |
768 | x->tx_buf = &ts->read_z1; | 963 | x->tx_buf = &ts->read_z1; |
769 | x->len = 1; | 964 | x->len = 1; |
770 | spi_message_add_tail(x, m); | 965 | spi_message_add_tail(x, m); |
@@ -774,14 +969,14 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
774 | x->len = 2; | 969 | x->len = 2; |
775 | spi_message_add_tail(x, m); | 970 | spi_message_add_tail(x, m); |
776 | 971 | ||
777 | m->complete = ads7846_debounce; | 972 | m->complete = ads7846_rx_val; |
778 | m->context = ts; | 973 | m->context = ts; |
779 | 974 | ||
780 | m++; | 975 | m++; |
781 | spi_message_init(m); | 976 | spi_message_init(m); |
782 | 977 | ||
783 | x++; | 978 | x++; |
784 | ts->read_z2 = READ_Z2; | 979 | ts->read_z2 = READ_Z2(vref); |
785 | x->tx_buf = &ts->read_z2; | 980 | x->tx_buf = &ts->read_z2; |
786 | x->len = 1; | 981 | x->len = 1; |
787 | spi_message_add_tail(x, m); | 982 | spi_message_add_tail(x, m); |
@@ -791,7 +986,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
791 | x->len = 2; | 986 | x->len = 2; |
792 | spi_message_add_tail(x, m); | 987 | spi_message_add_tail(x, m); |
793 | 988 | ||
794 | m->complete = ads7846_debounce; | 989 | m->complete = ads7846_rx_val; |
795 | m->context = ts; | 990 | m->context = ts; |
796 | } | 991 | } |
797 | 992 | ||
@@ -820,31 +1015,24 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
820 | spi->dev.driver->name, ts)) { | 1015 | spi->dev.driver->name, ts)) { |
821 | dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); | 1016 | dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); |
822 | err = -EBUSY; | 1017 | err = -EBUSY; |
823 | goto err_free_mem; | 1018 | goto err_cleanup_filter; |
824 | } | 1019 | } |
825 | 1020 | ||
1021 | err = ads784x_hwmon_register(spi, ts); | ||
1022 | if (err) | ||
1023 | goto err_free_irq; | ||
1024 | |||
826 | dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq); | 1025 | dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq); |
827 | 1026 | ||
828 | /* take a first sample, leaving nPENIRQ active; avoid | 1027 | /* take a first sample, leaving nPENIRQ active and vREF off; avoid |
829 | * the touchscreen, in case it's not connected. | 1028 | * the touchscreen, in case it's not connected. |
830 | */ | 1029 | */ |
831 | (void) ads7846_read12_ser(&spi->dev, | 1030 | (void) ads7846_read12_ser(&spi->dev, |
832 | READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); | 1031 | READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); |
833 | 1032 | ||
834 | switch (ts->model) { | 1033 | err = sysfs_create_group(&spi->dev.kobj, &ads784x_attr_group); |
835 | case 7846: | ||
836 | ts->attr_group = &ads7846_attr_group; | ||
837 | break; | ||
838 | case 7845: | ||
839 | ts->attr_group = &ads7845_attr_group; | ||
840 | break; | ||
841 | default: | ||
842 | ts->attr_group = &ads7843_attr_group; | ||
843 | break; | ||
844 | } | ||
845 | err = sysfs_create_group(&spi->dev.kobj, ts->attr_group); | ||
846 | if (err) | 1034 | if (err) |
847 | goto err_free_irq; | 1035 | goto err_remove_hwmon; |
848 | 1036 | ||
849 | err = input_register_device(input_dev); | 1037 | err = input_register_device(input_dev); |
850 | if (err) | 1038 | if (err) |
@@ -853,9 +1041,14 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
853 | return 0; | 1041 | return 0; |
854 | 1042 | ||
855 | err_remove_attr_group: | 1043 | err_remove_attr_group: |
856 | sysfs_remove_group(&spi->dev.kobj, ts->attr_group); | 1044 | sysfs_remove_group(&spi->dev.kobj, &ads784x_attr_group); |
1045 | err_remove_hwmon: | ||
1046 | ads784x_hwmon_unregister(spi, ts); | ||
857 | err_free_irq: | 1047 | err_free_irq: |
858 | free_irq(spi->irq, ts); | 1048 | free_irq(spi->irq, ts); |
1049 | err_cleanup_filter: | ||
1050 | if (ts->filter_cleanup) | ||
1051 | ts->filter_cleanup(ts->filter_data); | ||
859 | err_free_mem: | 1052 | err_free_mem: |
860 | input_free_device(input_dev); | 1053 | input_free_device(input_dev); |
861 | kfree(ts); | 1054 | kfree(ts); |
@@ -866,16 +1059,20 @@ static int __devexit ads7846_remove(struct spi_device *spi) | |||
866 | { | 1059 | { |
867 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | 1060 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); |
868 | 1061 | ||
1062 | ads784x_hwmon_unregister(spi, ts); | ||
869 | input_unregister_device(ts->input); | 1063 | input_unregister_device(ts->input); |
870 | 1064 | ||
871 | ads7846_suspend(spi, PMSG_SUSPEND); | 1065 | ads7846_suspend(spi, PMSG_SUSPEND); |
872 | 1066 | ||
873 | sysfs_remove_group(&spi->dev.kobj, ts->attr_group); | 1067 | sysfs_remove_group(&spi->dev.kobj, &ads784x_attr_group); |
874 | 1068 | ||
875 | free_irq(ts->spi->irq, ts); | 1069 | free_irq(ts->spi->irq, ts); |
876 | /* suspend left the IRQ disabled */ | 1070 | /* suspend left the IRQ disabled */ |
877 | enable_irq(ts->spi->irq); | 1071 | enable_irq(ts->spi->irq); |
878 | 1072 | ||
1073 | if (ts->filter_cleanup) | ||
1074 | ts->filter_cleanup(ts->filter_data); | ||
1075 | |||
879 | kfree(ts); | 1076 | kfree(ts); |
880 | 1077 | ||
881 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); | 1078 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); |
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c index a730c461227f..0300dca8591d 100644 --- a/drivers/input/tsdev.c +++ b/drivers/input/tsdev.c | |||
@@ -151,6 +151,10 @@ static int tsdev_open(struct inode *inode, struct file *file) | |||
151 | int i = iminor(inode) - TSDEV_MINOR_BASE; | 151 | int i = iminor(inode) - TSDEV_MINOR_BASE; |
152 | struct tsdev_list *list; | 152 | struct tsdev_list *list; |
153 | 153 | ||
154 | printk(KERN_WARNING "tsdev (compaq touchscreen emulation) is scheduled " | ||
155 | "for removal.\nSee Documentation/feature-removal-schedule.txt " | ||
156 | "for details.\n"); | ||
157 | |||
154 | if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK]) | 158 | if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK]) |
155 | return -ENODEV; | 159 | return -ENODEV; |
156 | 160 | ||
diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c index 5d145058a5cb..bc7f8e6f8c97 100644 --- a/drivers/usb/input/hid-ff.c +++ b/drivers/usb/input/hid-ff.c | |||
@@ -57,6 +57,7 @@ static struct hid_ff_initializer inits[] = { | |||
57 | { 0x46d, 0xc283, hid_lgff_init }, /* Logitech Wingman Force 3d */ | 57 | { 0x46d, 0xc283, hid_lgff_init }, /* Logitech Wingman Force 3d */ |
58 | { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */ | 58 | { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */ |
59 | { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */ | 59 | { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */ |
60 | { 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */ | ||
60 | #endif | 61 | #endif |
61 | #ifdef CONFIG_PANTHERLORD_FF | 62 | #ifdef CONFIG_PANTHERLORD_FF |
62 | { 0x810, 0x0001, hid_plff_init }, | 63 | { 0x810, 0x0001, hid_plff_init }, |
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c index 4f4fc3be192e..4df0968f852e 100644 --- a/drivers/usb/input/hid-lgff.c +++ b/drivers/usb/input/hid-lgff.c | |||
@@ -52,6 +52,7 @@ static const struct dev_type devices[] = { | |||
52 | { 0x046d, 0xc211, ff_rumble }, | 52 | { 0x046d, 0xc211, ff_rumble }, |
53 | { 0x046d, 0xc219, ff_rumble }, | 53 | { 0x046d, 0xc219, ff_rumble }, |
54 | { 0x046d, 0xc283, ff_joystick }, | 54 | { 0x046d, 0xc283, ff_joystick }, |
55 | { 0x046d, 0xca03, ff_joystick }, | ||
55 | { 0x0000, 0x0000, ff_joystick } | 56 | { 0x0000, 0x0000, ff_joystick } |
56 | }; | 57 | }; |
57 | 58 | ||
diff --git a/include/asm-arm/hardware/gpio_keys.h b/include/asm-arm/hardware/gpio_keys.h new file mode 100644 index 000000000000..2b217c7b9312 --- /dev/null +++ b/include/asm-arm/hardware/gpio_keys.h | |||
@@ -0,0 +1,17 @@ | |||
1 | #ifndef _GPIO_KEYS_H | ||
2 | #define _GPIO_KEYS_H | ||
3 | |||
4 | struct gpio_keys_button { | ||
5 | /* Configuration parameters */ | ||
6 | int keycode; | ||
7 | int gpio; | ||
8 | int active_low; | ||
9 | char *desc; | ||
10 | }; | ||
11 | |||
12 | struct gpio_keys_platform_data { | ||
13 | struct gpio_keys_button *buttons; | ||
14 | int nbuttons; | ||
15 | }; | ||
16 | |||
17 | #endif | ||
diff --git a/include/linux/spi/ads7846.h b/include/linux/spi/ads7846.h index adb3dafd33e9..3387e44dfd13 100644 --- a/include/linux/spi/ads7846.h +++ b/include/linux/spi/ads7846.h | |||
@@ -5,9 +5,17 @@ | |||
5 | * | 5 | * |
6 | * It's OK if the min/max values are zero. | 6 | * It's OK if the min/max values are zero. |
7 | */ | 7 | */ |
8 | enum ads7846_filter { | ||
9 | ADS7846_FILTER_OK, | ||
10 | ADS7846_FILTER_REPEAT, | ||
11 | ADS7846_FILTER_IGNORE, | ||
12 | }; | ||
13 | |||
8 | struct ads7846_platform_data { | 14 | struct ads7846_platform_data { |
9 | u16 model; /* 7843, 7845, 7846. */ | 15 | u16 model; /* 7843, 7845, 7846. */ |
10 | u16 vref_delay_usecs; /* 0 for external vref; etc */ | 16 | u16 vref_delay_usecs; /* 0 for external vref; etc */ |
17 | int keep_vref_on:1; /* set to keep vref on for differential | ||
18 | * measurements as well */ | ||
11 | u16 x_plate_ohms; | 19 | u16 x_plate_ohms; |
12 | u16 y_plate_ohms; | 20 | u16 y_plate_ohms; |
13 | 21 | ||
@@ -21,5 +29,9 @@ struct ads7846_platform_data { | |||
21 | u16 debounce_rep; /* additional consecutive good readings | 29 | u16 debounce_rep; /* additional consecutive good readings |
22 | * required after the first two */ | 30 | * required after the first two */ |
23 | int (*get_pendown_state)(void); | 31 | int (*get_pendown_state)(void); |
32 | int (*filter_init) (struct ads7846_platform_data *pdata, | ||
33 | void **filter_data); | ||
34 | int (*filter) (void *filter_data, int data_idx, int *val); | ||
35 | void (*filter_cleanup)(void *filter_data); | ||
24 | }; | 36 | }; |
25 | 37 | ||