diff options
63 files changed, 2380 insertions, 528 deletions
diff --git a/Documentation/input/input-programming.txt b/Documentation/input/input-programming.txt index 47fc86830cd7..81905e81585e 100644 --- a/Documentation/input/input-programming.txt +++ b/Documentation/input/input-programming.txt | |||
@@ -22,7 +22,7 @@ static struct input_dev *button_dev; | |||
22 | 22 | ||
23 | static void button_interrupt(int irq, void *dummy, struct pt_regs *fp) | 23 | static void button_interrupt(int irq, void *dummy, struct pt_regs *fp) |
24 | { | 24 | { |
25 | input_report_key(button_dev, BTN_1, inb(BUTTON_PORT) & 1); | 25 | input_report_key(button_dev, BTN_0, inb(BUTTON_PORT) & 1); |
26 | input_sync(button_dev); | 26 | input_sync(button_dev); |
27 | } | 27 | } |
28 | 28 | ||
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 9b26fa5edad6..f99112d50b41 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/mmc/host.h> | 21 | #include <linux/mmc/host.h> |
22 | #include <linux/pm.h> | 22 | #include <linux/pm.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/gpio_keys.h> | ||
25 | #include <linux/input.h> | ||
24 | 26 | ||
25 | #include <asm/setup.h> | 27 | #include <asm/setup.h> |
26 | #include <asm/memory.h> | 28 | #include <asm/memory.h> |
@@ -246,6 +248,46 @@ static struct platform_device tosakbd_device = { | |||
246 | .id = -1, | 248 | .id = -1, |
247 | }; | 249 | }; |
248 | 250 | ||
251 | static struct gpio_keys_button tosa_gpio_keys[] = { | ||
252 | { | ||
253 | .type = EV_PWR, | ||
254 | .code = KEY_SUSPEND, | ||
255 | .gpio = TOSA_GPIO_ON_KEY, | ||
256 | .desc = "On key", | ||
257 | .wakeup = 1, | ||
258 | .active_low = 1, | ||
259 | }, | ||
260 | { | ||
261 | .type = EV_KEY, | ||
262 | .code = TOSA_KEY_RECORD, | ||
263 | .gpio = TOSA_GPIO_RECORD_BTN, | ||
264 | .desc = "Record Button", | ||
265 | .wakeup = 1, | ||
266 | .active_low = 1, | ||
267 | }, | ||
268 | { | ||
269 | .type = EV_KEY, | ||
270 | .code = TOSA_KEY_SYNC, | ||
271 | .gpio = TOSA_GPIO_SYNC, | ||
272 | .desc = "Sync Button", | ||
273 | .wakeup = 1, | ||
274 | .active_low = 1, | ||
275 | }, | ||
276 | }; | ||
277 | |||
278 | static struct gpio_keys_platform_data tosa_gpio_keys_platform_data = { | ||
279 | .buttons = tosa_gpio_keys, | ||
280 | .nbuttons = ARRAY_SIZE(tosa_gpio_keys), | ||
281 | }; | ||
282 | |||
283 | static struct platform_device tosa_gpio_keys_device = { | ||
284 | .name = "gpio-keys", | ||
285 | .id = -1, | ||
286 | .dev = { | ||
287 | .platform_data = &tosa_gpio_keys_platform_data, | ||
288 | }, | ||
289 | }; | ||
290 | |||
249 | /* | 291 | /* |
250 | * Tosa LEDs | 292 | * Tosa LEDs |
251 | */ | 293 | */ |
@@ -258,6 +300,7 @@ static struct platform_device *devices[] __initdata = { | |||
258 | &tosascoop_device, | 300 | &tosascoop_device, |
259 | &tosascoop_jc_device, | 301 | &tosascoop_jc_device, |
260 | &tosakbd_device, | 302 | &tosakbd_device, |
303 | &tosa_gpio_keys_device, | ||
261 | &tosaled_device, | 304 | &tosaled_device, |
262 | }; | 305 | }; |
263 | 306 | ||
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 0295855a3eef..4a1b9bfc5471 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -292,7 +292,8 @@ firmware_class_timeout(u_long data) | |||
292 | 292 | ||
293 | static inline void fw_setup_device_id(struct device *f_dev, struct device *dev) | 293 | static inline void fw_setup_device_id(struct device *f_dev, struct device *dev) |
294 | { | 294 | { |
295 | snprintf(f_dev->bus_id, BUS_ID_SIZE, "firmware-%s", dev->bus_id); | 295 | /* XXX warning we should watch out for name collisions */ |
296 | strlcpy(f_dev->bus_id, dev->bus_id, BUS_ID_SIZE); | ||
296 | } | 297 | } |
297 | 298 | ||
298 | static int fw_register_device(struct device **dev_p, const char *fw_name, | 299 | static int fw_register_device(struct device **dev_p, const char *fw_name, |
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index 37bbf6729b4e..f8308bfb2613 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h | |||
@@ -187,7 +187,7 @@ typedef struct drm_i915_private { | |||
187 | u32 saveSWF2[3]; | 187 | u32 saveSWF2[3]; |
188 | u8 saveMSR; | 188 | u8 saveMSR; |
189 | u8 saveSR[8]; | 189 | u8 saveSR[8]; |
190 | u8 saveGR[24]; | 190 | u8 saveGR[25]; |
191 | u8 saveAR_INDEX; | 191 | u8 saveAR_INDEX; |
192 | u8 saveAR[20]; | 192 | u8 saveAR[20]; |
193 | u8 saveDACMASK; | 193 | u8 saveDACMASK; |
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index fc54d234507a..4dbd3425e928 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/kbd_kern.h> | 38 | #include <linux/kbd_kern.h> |
39 | #include <linux/kbd_diacr.h> | 39 | #include <linux/kbd_diacr.h> |
40 | #include <linux/vt_kern.h> | 40 | #include <linux/vt_kern.h> |
41 | #include <linux/consolemap.h> | ||
42 | #include <linux/sysrq.h> | 41 | #include <linux/sysrq.h> |
43 | #include <linux/input.h> | 42 | #include <linux/input.h> |
44 | #include <linux/reboot.h> | 43 | #include <linux/reboot.h> |
@@ -194,7 +193,7 @@ int getkeycode(unsigned int scancode) | |||
194 | int error = -ENODEV; | 193 | int error = -ENODEV; |
195 | 194 | ||
196 | list_for_each_entry(handle, &kbd_handler.h_list, h_node) { | 195 | list_for_each_entry(handle, &kbd_handler.h_list, h_node) { |
197 | error = handle->dev->getkeycode(handle->dev, scancode, &keycode); | 196 | error = input_get_keycode(handle->dev, scancode, &keycode); |
198 | if (!error) | 197 | if (!error) |
199 | return keycode; | 198 | return keycode; |
200 | } | 199 | } |
@@ -208,7 +207,7 @@ int setkeycode(unsigned int scancode, unsigned int keycode) | |||
208 | int error = -ENODEV; | 207 | int error = -ENODEV; |
209 | 208 | ||
210 | list_for_each_entry(handle, &kbd_handler.h_list, h_node) { | 209 | list_for_each_entry(handle, &kbd_handler.h_list, h_node) { |
211 | error = handle->dev->setkeycode(handle->dev, scancode, keycode); | 210 | error = input_set_keycode(handle->dev, scancode, keycode); |
212 | if (!error) | 211 | if (!error) |
213 | break; | 212 | break; |
214 | } | 213 | } |
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 63512d906f02..9dea14db724c 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig | |||
@@ -137,6 +137,18 @@ config INPUT_EVBUG | |||
137 | To compile this driver as a module, choose M here: the | 137 | To compile this driver as a module, choose M here: the |
138 | module will be called evbug. | 138 | module will be called evbug. |
139 | 139 | ||
140 | config INPUT_APMPOWER | ||
141 | tristate "Input Power Event -> APM Bridge" if EMBEDDED | ||
142 | depends on INPUT && APM_EMULATION | ||
143 | ---help--- | ||
144 | Say Y here if you want suspend key events to trigger a user | ||
145 | requested suspend through APM. This is useful on embedded | ||
146 | systems where such behviour is desired without userspace | ||
147 | interaction. If unsure, say N. | ||
148 | |||
149 | To compile this driver as a module, choose M here: the | ||
150 | module will be called apm-power. | ||
151 | |||
140 | comment "Input Device Drivers" | 152 | comment "Input Device Drivers" |
141 | 153 | ||
142 | source "drivers/input/keyboard/Kconfig" | 154 | source "drivers/input/keyboard/Kconfig" |
diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 99af903bd3ce..2ae87b19caa8 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile | |||
@@ -22,3 +22,4 @@ obj-$(CONFIG_INPUT_TABLET) += tablet/ | |||
22 | obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/ | 22 | obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/ |
23 | obj-$(CONFIG_INPUT_MISC) += misc/ | 23 | obj-$(CONFIG_INPUT_MISC) += misc/ |
24 | 24 | ||
25 | obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o | ||
diff --git a/drivers/input/apm-power.c b/drivers/input/apm-power.c new file mode 100644 index 000000000000..c36d110b349a --- /dev/null +++ b/drivers/input/apm-power.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * Input Power Event -> APM Bridge | ||
3 | * | ||
4 | * Copyright (c) 2007 Richard Purdie | ||
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 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/input.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/tty.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/pm.h> | ||
19 | #include <linux/apm-emulation.h> | ||
20 | |||
21 | static void system_power_event(unsigned int keycode) | ||
22 | { | ||
23 | switch (keycode) { | ||
24 | case KEY_SUSPEND: | ||
25 | apm_queue_event(APM_USER_SUSPEND); | ||
26 | |||
27 | printk(KERN_INFO "apm-power: Requesting system suspend...\n"); | ||
28 | break; | ||
29 | default: | ||
30 | break; | ||
31 | } | ||
32 | } | ||
33 | |||
34 | static void apmpower_event(struct input_handle *handle, unsigned int type, | ||
35 | unsigned int code, int value) | ||
36 | { | ||
37 | /* only react on key down events */ | ||
38 | if (value != 1) | ||
39 | return; | ||
40 | |||
41 | switch (type) { | ||
42 | case EV_PWR: | ||
43 | system_power_event(code); | ||
44 | break; | ||
45 | |||
46 | default: | ||
47 | break; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | static int apmpower_connect(struct input_handler *handler, | ||
52 | struct input_dev *dev, | ||
53 | const struct input_device_id *id) | ||
54 | { | ||
55 | struct input_handle *handle; | ||
56 | int error; | ||
57 | |||
58 | handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); | ||
59 | if (!handle) | ||
60 | return -ENOMEM; | ||
61 | |||
62 | handle->dev = dev; | ||
63 | handle->handler = handler; | ||
64 | handle->name = "apm-power"; | ||
65 | |||
66 | handler->private = handle; | ||
67 | |||
68 | error = input_register_handle(handle); | ||
69 | if (error) { | ||
70 | printk(KERN_ERR | ||
71 | "apm-power: Failed to register input power handler, " | ||
72 | "error %d\n", error); | ||
73 | kfree(handle); | ||
74 | return error; | ||
75 | } | ||
76 | |||
77 | error = input_open_device(handle); | ||
78 | if (error) { | ||
79 | printk(KERN_ERR | ||
80 | "apm-power: Failed to open input power device, " | ||
81 | "error %d\n", error); | ||
82 | input_unregister_handle(handle); | ||
83 | kfree(handle); | ||
84 | return error; | ||
85 | } | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static void apmpower_disconnect(struct input_handle *handler) | ||
91 | { | ||
92 | struct input_handle *handle = handler->private; | ||
93 | |||
94 | input_close_device(handle); | ||
95 | kfree(handle); | ||
96 | } | ||
97 | |||
98 | static const struct input_device_id apmpower_ids[] = { | ||
99 | { | ||
100 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT, | ||
101 | .evbit = { BIT_MASK(EV_PWR) }, | ||
102 | }, | ||
103 | { }, | ||
104 | }; | ||
105 | |||
106 | MODULE_DEVICE_TABLE(input, apmpower_ids); | ||
107 | |||
108 | static struct input_handler apmpower_handler = { | ||
109 | .event = apmpower_event, | ||
110 | .connect = apmpower_connect, | ||
111 | .disconnect = apmpower_disconnect, | ||
112 | .name = "apm-power", | ||
113 | .id_table = apmpower_ids, | ||
114 | }; | ||
115 | |||
116 | static int __init apmpower_init(void) | ||
117 | { | ||
118 | return input_register_handler(&apmpower_handler); | ||
119 | } | ||
120 | |||
121 | static void __exit apmpower_exit(void) | ||
122 | { | ||
123 | input_unregister_handler(&apmpower_handler); | ||
124 | } | ||
125 | |||
126 | module_init(apmpower_init); | ||
127 | module_exit(apmpower_exit); | ||
128 | |||
129 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); | ||
130 | MODULE_DESCRIPTION("Input Power Event -> APM Bridge"); | ||
131 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index e5b4e9bfbdc5..0727b0a12557 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -617,7 +617,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
617 | if (get_user(t, ip)) | 617 | if (get_user(t, ip)) |
618 | return -EFAULT; | 618 | return -EFAULT; |
619 | 619 | ||
620 | error = dev->getkeycode(dev, t, &v); | 620 | error = input_get_keycode(dev, t, &v); |
621 | if (error) | 621 | if (error) |
622 | return error; | 622 | return error; |
623 | 623 | ||
@@ -630,7 +630,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
630 | if (get_user(t, ip) || get_user(v, ip + 1)) | 630 | if (get_user(t, ip) || get_user(v, ip + 1)) |
631 | return -EFAULT; | 631 | return -EFAULT; |
632 | 632 | ||
633 | return dev->setkeycode(dev, t, v); | 633 | return input_set_keycode(dev, t, v); |
634 | 634 | ||
635 | case EVIOCSFF: | 635 | case EVIOCSFF: |
636 | if (copy_from_user(&effect, p, sizeof(effect))) | 636 | if (copy_from_user(&effect, p, sizeof(effect))) |
@@ -683,7 +683,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
683 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | 683 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; |
684 | case EV_SW: bits = dev->swbit; len = SW_MAX; break; | 684 | case EV_SW: bits = dev->swbit; len = SW_MAX; break; |
685 | default: return -EINVAL; | 685 | default: return -EINVAL; |
686 | } | 686 | } |
687 | return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); | 687 | return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); |
688 | } | 688 | } |
689 | 689 | ||
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c index 92b359894e81..490918a5d192 100644 --- a/drivers/input/input-polldev.c +++ b/drivers/input/input-polldev.c | |||
@@ -60,17 +60,21 @@ static void input_polled_device_work(struct work_struct *work) | |||
60 | { | 60 | { |
61 | struct input_polled_dev *dev = | 61 | struct input_polled_dev *dev = |
62 | container_of(work, struct input_polled_dev, work.work); | 62 | container_of(work, struct input_polled_dev, work.work); |
63 | unsigned long delay; | ||
63 | 64 | ||
64 | dev->poll(dev); | 65 | dev->poll(dev); |
65 | queue_delayed_work(polldev_wq, &dev->work, | 66 | |
66 | msecs_to_jiffies(dev->poll_interval)); | 67 | delay = msecs_to_jiffies(dev->poll_interval); |
68 | if (delay >= HZ) | ||
69 | delay = round_jiffies_relative(delay); | ||
70 | |||
71 | queue_delayed_work(polldev_wq, &dev->work, delay); | ||
67 | } | 72 | } |
68 | 73 | ||
69 | static int input_open_polled_device(struct input_dev *input) | 74 | static int input_open_polled_device(struct input_dev *input) |
70 | { | 75 | { |
71 | struct input_polled_dev *dev = input->private; | 76 | struct input_polled_dev *dev = input->private; |
72 | int error; | 77 | int error; |
73 | unsigned long ticks; | ||
74 | 78 | ||
75 | error = input_polldev_start_workqueue(); | 79 | error = input_polldev_start_workqueue(); |
76 | if (error) | 80 | if (error) |
@@ -79,10 +83,8 @@ static int input_open_polled_device(struct input_dev *input) | |||
79 | if (dev->flush) | 83 | if (dev->flush) |
80 | dev->flush(dev); | 84 | dev->flush(dev); |
81 | 85 | ||
82 | ticks = msecs_to_jiffies(dev->poll_interval); | 86 | queue_delayed_work(polldev_wq, &dev->work, |
83 | if (ticks >= HZ) | 87 | msecs_to_jiffies(dev->poll_interval)); |
84 | ticks = round_jiffies(ticks); | ||
85 | queue_delayed_work(polldev_wq, &dev->work, ticks); | ||
86 | 88 | ||
87 | return 0; | 89 | return 0; |
88 | } | 90 | } |
@@ -91,7 +93,7 @@ static void input_close_polled_device(struct input_dev *input) | |||
91 | { | 93 | { |
92 | struct input_polled_dev *dev = input->private; | 94 | struct input_polled_dev *dev = input->private; |
93 | 95 | ||
94 | cancel_rearming_delayed_workqueue(polldev_wq, &dev->work); | 96 | cancel_delayed_work_sync(&dev->work); |
95 | input_polldev_stop_workqueue(); | 97 | input_polldev_stop_workqueue(); |
96 | } | 98 | } |
97 | 99 | ||
diff --git a/drivers/input/input.c b/drivers/input/input.c index a0be978501ff..f02c242c3114 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -493,7 +493,7 @@ static void input_disconnect_device(struct input_dev *dev) | |||
493 | if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) { | 493 | if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) { |
494 | for (code = 0; code <= KEY_MAX; code++) { | 494 | for (code = 0; code <= KEY_MAX; code++) { |
495 | if (is_event_supported(code, dev->keybit, KEY_MAX) && | 495 | if (is_event_supported(code, dev->keybit, KEY_MAX) && |
496 | test_bit(code, dev->key)) { | 496 | __test_and_clear_bit(code, dev->key)) { |
497 | input_pass_event(dev, EV_KEY, code, 0); | 497 | input_pass_event(dev, EV_KEY, code, 0); |
498 | } | 498 | } |
499 | } | 499 | } |
@@ -526,7 +526,7 @@ static int input_default_getkeycode(struct input_dev *dev, | |||
526 | if (!dev->keycodesize) | 526 | if (!dev->keycodesize) |
527 | return -EINVAL; | 527 | return -EINVAL; |
528 | 528 | ||
529 | if (scancode < 0 || scancode >= dev->keycodemax) | 529 | if (scancode >= dev->keycodemax) |
530 | return -EINVAL; | 530 | return -EINVAL; |
531 | 531 | ||
532 | *keycode = input_fetch_keycode(dev, scancode); | 532 | *keycode = input_fetch_keycode(dev, scancode); |
@@ -540,10 +540,7 @@ static int input_default_setkeycode(struct input_dev *dev, | |||
540 | int old_keycode; | 540 | int old_keycode; |
541 | int i; | 541 | int i; |
542 | 542 | ||
543 | if (scancode < 0 || scancode >= dev->keycodemax) | 543 | if (scancode >= dev->keycodemax) |
544 | return -EINVAL; | ||
545 | |||
546 | if (keycode < 0 || keycode > KEY_MAX) | ||
547 | return -EINVAL; | 544 | return -EINVAL; |
548 | 545 | ||
549 | if (!dev->keycodesize) | 546 | if (!dev->keycodesize) |
@@ -586,6 +583,75 @@ static int input_default_setkeycode(struct input_dev *dev, | |||
586 | return 0; | 583 | return 0; |
587 | } | 584 | } |
588 | 585 | ||
586 | /** | ||
587 | * input_get_keycode - retrieve keycode currently mapped to a given scancode | ||
588 | * @dev: input device which keymap is being queried | ||
589 | * @scancode: scancode (or its equivalent for device in question) for which | ||
590 | * keycode is needed | ||
591 | * @keycode: result | ||
592 | * | ||
593 | * This function should be called by anyone interested in retrieving current | ||
594 | * keymap. Presently keyboard and evdev handlers use it. | ||
595 | */ | ||
596 | int input_get_keycode(struct input_dev *dev, int scancode, int *keycode) | ||
597 | { | ||
598 | if (scancode < 0) | ||
599 | return -EINVAL; | ||
600 | |||
601 | return dev->getkeycode(dev, scancode, keycode); | ||
602 | } | ||
603 | EXPORT_SYMBOL(input_get_keycode); | ||
604 | |||
605 | /** | ||
606 | * input_get_keycode - assign new keycode to a given scancode | ||
607 | * @dev: input device which keymap is being updated | ||
608 | * @scancode: scancode (or its equivalent for device in question) | ||
609 | * @keycode: new keycode to be assigned to the scancode | ||
610 | * | ||
611 | * This function should be called by anyone needing to update current | ||
612 | * keymap. Presently keyboard and evdev handlers use it. | ||
613 | */ | ||
614 | int input_set_keycode(struct input_dev *dev, int scancode, int keycode) | ||
615 | { | ||
616 | unsigned long flags; | ||
617 | int old_keycode; | ||
618 | int retval; | ||
619 | |||
620 | if (scancode < 0) | ||
621 | return -EINVAL; | ||
622 | |||
623 | if (keycode < 0 || keycode > KEY_MAX) | ||
624 | return -EINVAL; | ||
625 | |||
626 | spin_lock_irqsave(&dev->event_lock, flags); | ||
627 | |||
628 | retval = dev->getkeycode(dev, scancode, &old_keycode); | ||
629 | if (retval) | ||
630 | goto out; | ||
631 | |||
632 | retval = dev->setkeycode(dev, scancode, keycode); | ||
633 | if (retval) | ||
634 | goto out; | ||
635 | |||
636 | /* | ||
637 | * Simulate keyup event if keycode is not present | ||
638 | * in the keymap anymore | ||
639 | */ | ||
640 | if (test_bit(EV_KEY, dev->evbit) && | ||
641 | !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && | ||
642 | __test_and_clear_bit(old_keycode, dev->key)) { | ||
643 | |||
644 | input_pass_event(dev, EV_KEY, old_keycode, 0); | ||
645 | if (dev->sync) | ||
646 | input_pass_event(dev, EV_SYN, SYN_REPORT, 1); | ||
647 | } | ||
648 | |||
649 | out: | ||
650 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
651 | |||
652 | return retval; | ||
653 | } | ||
654 | EXPORT_SYMBOL(input_set_keycode); | ||
589 | 655 | ||
590 | #define MATCH_BIT(bit, max) \ | 656 | #define MATCH_BIT(bit, max) \ |
591 | for (i = 0; i < BITS_TO_LONGS(max); i++) \ | 657 | for (i = 0; i < BITS_TO_LONGS(max); i++) \ |
@@ -755,7 +821,7 @@ static int input_devices_seq_show(struct seq_file *seq, void *v) | |||
755 | return 0; | 821 | return 0; |
756 | } | 822 | } |
757 | 823 | ||
758 | static struct seq_operations input_devices_seq_ops = { | 824 | static const struct seq_operations input_devices_seq_ops = { |
759 | .start = input_devices_seq_start, | 825 | .start = input_devices_seq_start, |
760 | .next = input_devices_seq_next, | 826 | .next = input_devices_seq_next, |
761 | .stop = input_devices_seq_stop, | 827 | .stop = input_devices_seq_stop, |
@@ -808,7 +874,7 @@ static int input_handlers_seq_show(struct seq_file *seq, void *v) | |||
808 | 874 | ||
809 | return 0; | 875 | return 0; |
810 | } | 876 | } |
811 | static struct seq_operations input_handlers_seq_ops = { | 877 | static const struct seq_operations input_handlers_seq_ops = { |
812 | .start = input_handlers_seq_start, | 878 | .start = input_handlers_seq_start, |
813 | .next = input_handlers_seq_next, | 879 | .next = input_handlers_seq_next, |
814 | .stop = input_handlers_seq_stop, | 880 | .stop = input_handlers_seq_stop, |
@@ -1329,9 +1395,6 @@ int input_register_device(struct input_dev *dev) | |||
1329 | snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), | 1395 | snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), |
1330 | "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); | 1396 | "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); |
1331 | 1397 | ||
1332 | if (dev->cdev.dev) | ||
1333 | dev->dev.parent = dev->cdev.dev; | ||
1334 | |||
1335 | error = device_add(&dev->dev); | 1398 | error = device_add(&dev->dev); |
1336 | if (error) | 1399 | if (error) |
1337 | return error; | 1400 | return error; |
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c index 5cf9f3610e67..deb9f825f92c 100644 --- a/drivers/input/joystick/amijoy.c +++ b/drivers/input/joystick/amijoy.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/errno.h> | 32 | #include <linux/errno.h> |
33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
35 | #include <linux/moduleparam.h> | ||
36 | #include <linux/init.h> | 35 | #include <linux/init.h> |
37 | #include <linux/input.h> | 36 | #include <linux/input.h> |
38 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 15739880afc6..f32e031dcb27 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/moduleparam.h> | ||
35 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
36 | #include <linux/bitops.h> | 35 | #include <linux/bitops.h> |
37 | #include <linux/init.h> | 36 | #include <linux/init.h> |
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index a6ca9d5e252f..960e501c60c8 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c | |||
@@ -33,7 +33,6 @@ | |||
33 | 33 | ||
34 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
36 | #include <linux/moduleparam.h> | ||
37 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
38 | #include <linux/init.h> | 37 | #include <linux/init.h> |
39 | #include <linux/parport.h> | 38 | #include <linux/parport.h> |
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index df2a9d02ca6c..07a32aff5a31 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
36 | #include <linux/moduleparam.h> | ||
37 | #include <linux/init.h> | 36 | #include <linux/init.h> |
38 | #include <linux/parport.h> | 37 | #include <linux/parport.h> |
39 | #include <linux/input.h> | 38 | #include <linux/input.h> |
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 6f826b37d9aa..a2517fa72eb8 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c | |||
@@ -85,7 +85,7 @@ static struct iforce_device iforce_device[] = { | |||
85 | 85 | ||
86 | static int iforce_playback(struct input_dev *dev, int effect_id, int value) | 86 | static int iforce_playback(struct input_dev *dev, int effect_id, int value) |
87 | { | 87 | { |
88 | struct iforce* iforce = dev->private; | 88 | struct iforce *iforce = input_get_drvdata(dev); |
89 | struct iforce_core_effect *core_effect = &iforce->core_effects[effect_id]; | 89 | struct iforce_core_effect *core_effect = &iforce->core_effects[effect_id]; |
90 | 90 | ||
91 | if (value > 0) | 91 | if (value > 0) |
@@ -99,7 +99,7 @@ static int iforce_playback(struct input_dev *dev, int effect_id, int value) | |||
99 | 99 | ||
100 | static void iforce_set_gain(struct input_dev *dev, u16 gain) | 100 | static void iforce_set_gain(struct input_dev *dev, u16 gain) |
101 | { | 101 | { |
102 | struct iforce* iforce = dev->private; | 102 | struct iforce *iforce = input_get_drvdata(dev); |
103 | unsigned char data[3]; | 103 | unsigned char data[3]; |
104 | 104 | ||
105 | data[0] = gain >> 9; | 105 | data[0] = gain >> 9; |
@@ -108,7 +108,7 @@ static void iforce_set_gain(struct input_dev *dev, u16 gain) | |||
108 | 108 | ||
109 | static void iforce_set_autocenter(struct input_dev *dev, u16 magnitude) | 109 | static void iforce_set_autocenter(struct input_dev *dev, u16 magnitude) |
110 | { | 110 | { |
111 | struct iforce* iforce = dev->private; | 111 | struct iforce *iforce = input_get_drvdata(dev); |
112 | unsigned char data[3]; | 112 | unsigned char data[3]; |
113 | 113 | ||
114 | data[0] = 0x03; | 114 | data[0] = 0x03; |
@@ -126,7 +126,7 @@ static void iforce_set_autocenter(struct input_dev *dev, u16 magnitude) | |||
126 | */ | 126 | */ |
127 | static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) | 127 | static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) |
128 | { | 128 | { |
129 | struct iforce* iforce = dev->private; | 129 | struct iforce *iforce = input_get_drvdata(dev); |
130 | struct iforce_core_effect *core_effect = &iforce->core_effects[effect->id]; | 130 | struct iforce_core_effect *core_effect = &iforce->core_effects[effect->id]; |
131 | int ret; | 131 | int ret; |
132 | 132 | ||
@@ -173,7 +173,7 @@ static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect, | |||
173 | */ | 173 | */ |
174 | static int iforce_erase_effect(struct input_dev *dev, int effect_id) | 174 | static int iforce_erase_effect(struct input_dev *dev, int effect_id) |
175 | { | 175 | { |
176 | struct iforce *iforce = dev->private; | 176 | struct iforce *iforce = input_get_drvdata(dev); |
177 | struct iforce_core_effect *core_effect = &iforce->core_effects[effect_id]; | 177 | struct iforce_core_effect *core_effect = &iforce->core_effects[effect_id]; |
178 | int err = 0; | 178 | int err = 0; |
179 | 179 | ||
@@ -191,7 +191,7 @@ static int iforce_erase_effect(struct input_dev *dev, int effect_id) | |||
191 | 191 | ||
192 | static int iforce_open(struct input_dev *dev) | 192 | static int iforce_open(struct input_dev *dev) |
193 | { | 193 | { |
194 | struct iforce *iforce = dev->private; | 194 | struct iforce *iforce = input_get_drvdata(dev); |
195 | 195 | ||
196 | switch (iforce->bus) { | 196 | switch (iforce->bus) { |
197 | #ifdef CONFIG_JOYSTICK_IFORCE_USB | 197 | #ifdef CONFIG_JOYSTICK_IFORCE_USB |
@@ -213,7 +213,7 @@ static int iforce_open(struct input_dev *dev) | |||
213 | 213 | ||
214 | static void iforce_release(struct input_dev *dev) | 214 | static void iforce_release(struct input_dev *dev) |
215 | { | 215 | { |
216 | struct iforce *iforce = dev->private; | 216 | struct iforce *iforce = input_get_drvdata(dev); |
217 | int i; | 217 | int i; |
218 | 218 | ||
219 | if (test_bit(EV_FF, dev->evbit)) { | 219 | if (test_bit(EV_FF, dev->evbit)) { |
@@ -298,7 +298,8 @@ int iforce_init_device(struct iforce *iforce) | |||
298 | #endif | 298 | #endif |
299 | } | 299 | } |
300 | 300 | ||
301 | input_dev->private = iforce; | 301 | input_set_drvdata(input_dev, iforce); |
302 | |||
302 | input_dev->name = "Unknown I-Force device"; | 303 | input_dev->name = "Unknown I-Force device"; |
303 | input_dev->open = iforce_open; | 304 | input_dev->open = iforce_open; |
304 | input_dev->close = iforce_release; | 305 | input_dev->close = iforce_release; |
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index bbebd4e2ad7f..989483f53160 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <linux/parport.h> | 35 | #include <linux/parport.h> |
36 | #include <linux/input.h> | 36 | #include <linux/input.h> |
37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
38 | #include <linux/moduleparam.h> | ||
39 | #include <linux/init.h> | 38 | #include <linux/init.h> |
40 | #include <linux/mutex.h> | 39 | #include <linux/mutex.h> |
41 | 40 | ||
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 6e9d75bd2b15..0380597249bb 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -75,7 +75,6 @@ | |||
75 | #include <linux/slab.h> | 75 | #include <linux/slab.h> |
76 | #include <linux/stat.h> | 76 | #include <linux/stat.h> |
77 | #include <linux/module.h> | 77 | #include <linux/module.h> |
78 | #include <linux/moduleparam.h> | ||
79 | #include <linux/usb/input.h> | 78 | #include <linux/usb/input.h> |
80 | 79 | ||
81 | #define DRIVER_VERSION "v0.0.6" | 80 | #define DRIVER_VERSION "v0.0.6" |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 086d58c0ccbe..8ea709be3306 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -154,6 +154,27 @@ config KEYBOARD_SPITZ | |||
154 | To compile this driver as a module, choose M here: the | 154 | To compile this driver as a module, choose M here: the |
155 | module will be called spitzkbd. | 155 | module will be called spitzkbd. |
156 | 156 | ||
157 | config KEYBOARD_TOSA | ||
158 | tristate "Tosa keyboard" | ||
159 | depends on MACH_TOSA | ||
160 | default y | ||
161 | help | ||
162 | Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) | ||
163 | |||
164 | To compile this driver as a module, choose M here: the | ||
165 | module will be called tosakbd. | ||
166 | |||
167 | config KEYBOARD_TOSA_USE_EXT_KEYCODES | ||
168 | bool "Tosa keyboard: use extended keycodes" | ||
169 | depends on KEYBOARD_TOSA | ||
170 | default n | ||
171 | help | ||
172 | Say Y here to enable the tosa keyboard driver to generate extended | ||
173 | (>= 127) keycodes. Be aware, that they can't be correctly interpreted | ||
174 | by either console keyboard driver or by Kdrive keybd driver. | ||
175 | |||
176 | Say Y only if you know, what you are doing! | ||
177 | |||
157 | config KEYBOARD_AMIGA | 178 | config KEYBOARD_AMIGA |
158 | tristate "Amiga keyboard" | 179 | tristate "Amiga keyboard" |
159 | depends on AMIGA | 180 | depends on AMIGA |
@@ -239,13 +260,13 @@ config KEYBOARD_OMAP | |||
239 | module will be called omap-keypad. | 260 | module will be called omap-keypad. |
240 | 261 | ||
241 | config KEYBOARD_PXA27x | 262 | config KEYBOARD_PXA27x |
242 | tristate "PXA27x keyboard support" | 263 | tristate "PXA27x/PXA3xx keypad support" |
243 | depends on PXA27x | 264 | depends on PXA27x || PXA3xx |
244 | help | 265 | help |
245 | Enable support for PXA27x matrix keyboard controller | 266 | Enable support for PXA27x/PXA3xx keypad controller |
246 | 267 | ||
247 | To compile this driver as a module, choose M here: the | 268 | To compile this driver as a module, choose M here: the |
248 | module will be called pxa27x_keyboard. | 269 | module will be called pxa27x_keypad. |
249 | 270 | ||
250 | config KEYBOARD_AAED2000 | 271 | config KEYBOARD_AAED2000 |
251 | tristate "AAED-2000 keyboard" | 272 | tristate "AAED-2000 keyboard" |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index e97455fdcc83..e741f4031012 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -15,10 +15,11 @@ obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o | |||
15 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | 15 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
16 | obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o | 16 | obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o |
17 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o | 17 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o |
18 | obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o | ||
18 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o | 19 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o |
19 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o | 20 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o |
20 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o | 21 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o |
21 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o | 22 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o |
22 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o | 23 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o |
23 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o | 24 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o |
24 | obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o | 25 | obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o |
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index b39c5b31e620..4a95adc4cc78 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -19,7 +19,6 @@ | |||
19 | 19 | ||
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/moduleparam.h> | ||
23 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
24 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
25 | #include <linux/init.h> | 24 | #include <linux/init.h> |
@@ -28,6 +27,7 @@ | |||
28 | #include <linux/workqueue.h> | 27 | #include <linux/workqueue.h> |
29 | #include <linux/libps2.h> | 28 | #include <linux/libps2.h> |
30 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
30 | #include <linux/dmi.h> | ||
31 | 31 | ||
32 | #define DRIVER_DESC "AT and PS/2 keyboard driver" | 32 | #define DRIVER_DESC "AT and PS/2 keyboard driver" |
33 | 33 | ||
@@ -201,6 +201,7 @@ struct atkbd { | |||
201 | 201 | ||
202 | unsigned short id; | 202 | unsigned short id; |
203 | unsigned char keycode[512]; | 203 | unsigned char keycode[512]; |
204 | DECLARE_BITMAP(force_release_mask, 512); | ||
204 | unsigned char set; | 205 | unsigned char set; |
205 | unsigned char translated; | 206 | unsigned char translated; |
206 | unsigned char extra; | 207 | unsigned char extra; |
@@ -225,6 +226,11 @@ struct atkbd { | |||
225 | unsigned long event_mask; | 226 | unsigned long event_mask; |
226 | }; | 227 | }; |
227 | 228 | ||
229 | /* | ||
230 | * System-specific ketymap fixup routine | ||
231 | */ | ||
232 | static void (*atkbd_platform_fixup)(struct atkbd *); | ||
233 | |||
228 | static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, | 234 | static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, |
229 | ssize_t (*handler)(struct atkbd *, char *)); | 235 | ssize_t (*handler)(struct atkbd *, char *)); |
230 | static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count, | 236 | static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count, |
@@ -349,7 +355,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | |||
349 | struct atkbd *atkbd = serio_get_drvdata(serio); | 355 | struct atkbd *atkbd = serio_get_drvdata(serio); |
350 | struct input_dev *dev = atkbd->dev; | 356 | struct input_dev *dev = atkbd->dev; |
351 | unsigned int code = data; | 357 | unsigned int code = data; |
352 | int scroll = 0, hscroll = 0, click = -1, add_release_event = 0; | 358 | int scroll = 0, hscroll = 0, click = -1; |
353 | int value; | 359 | int value; |
354 | unsigned char keycode; | 360 | unsigned char keycode; |
355 | 361 | ||
@@ -414,14 +420,6 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | |||
414 | "Some program might be trying access hardware directly.\n", | 420 | "Some program might be trying access hardware directly.\n", |
415 | data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); | 421 | data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); |
416 | goto out; | 422 | goto out; |
417 | case ATKBD_RET_HANGEUL: | ||
418 | case ATKBD_RET_HANJA: | ||
419 | /* | ||
420 | * These keys do not report release and thus need to be | ||
421 | * flagged properly | ||
422 | */ | ||
423 | add_release_event = 1; | ||
424 | break; | ||
425 | case ATKBD_RET_ERR: | 423 | case ATKBD_RET_ERR: |
426 | atkbd->err_count++; | 424 | atkbd->err_count++; |
427 | #ifdef ATKBD_DEBUG | 425 | #ifdef ATKBD_DEBUG |
@@ -491,7 +489,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | |||
491 | input_event(dev, EV_KEY, keycode, value); | 489 | input_event(dev, EV_KEY, keycode, value); |
492 | input_sync(dev); | 490 | input_sync(dev); |
493 | 491 | ||
494 | if (value && add_release_event) { | 492 | if (value && test_bit(code, atkbd->force_release_mask)) { |
495 | input_report_key(dev, keycode, 0); | 493 | input_report_key(dev, keycode, 0); |
496 | input_sync(dev); | 494 | input_sync(dev); |
497 | } | 495 | } |
@@ -824,7 +822,6 @@ static void atkbd_disconnect(struct serio *serio) | |||
824 | atkbd_disable(atkbd); | 822 | atkbd_disable(atkbd); |
825 | 823 | ||
826 | /* make sure we don't have a command in flight */ | 824 | /* make sure we don't have a command in flight */ |
827 | synchronize_sched(); /* Allow atkbd_interrupt()s to complete. */ | ||
828 | flush_scheduled_work(); | 825 | flush_scheduled_work(); |
829 | 826 | ||
830 | sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group); | 827 | sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group); |
@@ -834,6 +831,22 @@ static void atkbd_disconnect(struct serio *serio) | |||
834 | kfree(atkbd); | 831 | kfree(atkbd); |
835 | } | 832 | } |
836 | 833 | ||
834 | /* | ||
835 | * Most special keys (Fn+F?) on Dell Latitudes do not generate release | ||
836 | * events so we have to do it ourselves. | ||
837 | */ | ||
838 | static void atkbd_latitude_keymap_fixup(struct atkbd *atkbd) | ||
839 | { | ||
840 | const unsigned int forced_release_keys[] = { | ||
841 | 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, | ||
842 | }; | ||
843 | int i; | ||
844 | |||
845 | if (atkbd->set == 2) | ||
846 | for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) | ||
847 | __set_bit(forced_release_keys[i], | ||
848 | atkbd->force_release_mask); | ||
849 | } | ||
837 | 850 | ||
838 | /* | 851 | /* |
839 | * atkbd_set_keycode_table() initializes keyboard's keycode table | 852 | * atkbd_set_keycode_table() initializes keyboard's keycode table |
@@ -842,17 +855,20 @@ static void atkbd_disconnect(struct serio *serio) | |||
842 | 855 | ||
843 | static void atkbd_set_keycode_table(struct atkbd *atkbd) | 856 | static void atkbd_set_keycode_table(struct atkbd *atkbd) |
844 | { | 857 | { |
858 | unsigned int scancode; | ||
845 | int i, j; | 859 | int i, j; |
846 | 860 | ||
847 | memset(atkbd->keycode, 0, sizeof(atkbd->keycode)); | 861 | memset(atkbd->keycode, 0, sizeof(atkbd->keycode)); |
862 | bitmap_zero(atkbd->force_release_mask, 512); | ||
848 | 863 | ||
849 | if (atkbd->translated) { | 864 | if (atkbd->translated) { |
850 | for (i = 0; i < 128; i++) { | 865 | for (i = 0; i < 128; i++) { |
851 | atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]]; | 866 | scancode = atkbd_unxlate_table[i]; |
852 | atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80]; | 867 | atkbd->keycode[i] = atkbd_set2_keycode[scancode]; |
868 | atkbd->keycode[i | 0x80] = atkbd_set2_keycode[scancode | 0x80]; | ||
853 | if (atkbd->scroll) | 869 | if (atkbd->scroll) |
854 | for (j = 0; j < ARRAY_SIZE(atkbd_scroll_keys); j++) | 870 | for (j = 0; j < ARRAY_SIZE(atkbd_scroll_keys); j++) |
855 | if ((atkbd_unxlate_table[i] | 0x80) == atkbd_scroll_keys[j].set2) | 871 | if ((scancode | 0x80) == atkbd_scroll_keys[j].set2) |
856 | atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j].keycode; | 872 | atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j].keycode; |
857 | } | 873 | } |
858 | } else if (atkbd->set == 3) { | 874 | } else if (atkbd->set == 3) { |
@@ -861,12 +877,29 @@ static void atkbd_set_keycode_table(struct atkbd *atkbd) | |||
861 | memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode)); | 877 | memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode)); |
862 | 878 | ||
863 | if (atkbd->scroll) | 879 | if (atkbd->scroll) |
864 | for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++) | 880 | for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++) { |
865 | atkbd->keycode[atkbd_scroll_keys[i].set2] = atkbd_scroll_keys[i].keycode; | 881 | scancode = atkbd_scroll_keys[i].set2; |
882 | atkbd->keycode[scancode] = atkbd_scroll_keys[i].keycode; | ||
883 | } | ||
866 | } | 884 | } |
867 | 885 | ||
868 | atkbd->keycode[atkbd_compat_scancode(atkbd, ATKBD_RET_HANGEUL)] = KEY_HANGUEL; | 886 | /* |
869 | atkbd->keycode[atkbd_compat_scancode(atkbd, ATKBD_RET_HANJA)] = KEY_HANJA; | 887 | * HANGEUL and HANJA keys do not send release events so we need to |
888 | * generate such events ourselves | ||
889 | */ | ||
890 | scancode = atkbd_compat_scancode(atkbd, ATKBD_RET_HANGEUL); | ||
891 | atkbd->keycode[scancode] = KEY_HANGEUL; | ||
892 | __set_bit(scancode, atkbd->force_release_mask); | ||
893 | |||
894 | scancode = atkbd_compat_scancode(atkbd, ATKBD_RET_HANJA); | ||
895 | atkbd->keycode[scancode] = KEY_HANJA; | ||
896 | __set_bit(scancode, atkbd->force_release_mask); | ||
897 | |||
898 | /* | ||
899 | * Perform additional fixups | ||
900 | */ | ||
901 | if (atkbd_platform_fixup) | ||
902 | atkbd_platform_fixup(atkbd); | ||
870 | } | 903 | } |
871 | 904 | ||
872 | /* | 905 | /* |
@@ -1401,9 +1434,29 @@ static ssize_t atkbd_show_err_count(struct atkbd *atkbd, char *buf) | |||
1401 | return sprintf(buf, "%lu\n", atkbd->err_count); | 1434 | return sprintf(buf, "%lu\n", atkbd->err_count); |
1402 | } | 1435 | } |
1403 | 1436 | ||
1437 | static int __init atkbd_setup_fixup(const struct dmi_system_id *id) | ||
1438 | { | ||
1439 | atkbd_platform_fixup = id->driver_data; | ||
1440 | return 0; | ||
1441 | } | ||
1442 | |||
1443 | static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | ||
1444 | { | ||
1445 | .ident = "Dell Latitude series", | ||
1446 | .matches = { | ||
1447 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
1448 | DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"), | ||
1449 | }, | ||
1450 | .callback = atkbd_setup_fixup, | ||
1451 | .driver_data = atkbd_latitude_keymap_fixup, | ||
1452 | }, | ||
1453 | { } | ||
1454 | }; | ||
1404 | 1455 | ||
1405 | static int __init atkbd_init(void) | 1456 | static int __init atkbd_init(void) |
1406 | { | 1457 | { |
1458 | dmi_check_system(atkbd_dmi_quirk_table); | ||
1459 | |||
1407 | return serio_register_driver(&atkbd_drv); | 1460 | return serio_register_driver(&atkbd_drv); |
1408 | } | 1461 | } |
1409 | 1462 | ||
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 1b08f4e79dd2..32e2c2605d95 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c | |||
@@ -64,7 +64,6 @@ | |||
64 | #include <linux/delay.h> | 64 | #include <linux/delay.h> |
65 | #include <linux/slab.h> | 65 | #include <linux/slab.h> |
66 | #include <linux/module.h> | 66 | #include <linux/module.h> |
67 | #include <linux/moduleparam.h> | ||
68 | #include <linux/interrupt.h> | 67 | #include <linux/interrupt.h> |
69 | #include <linux/init.h> | 68 | #include <linux/init.h> |
70 | #include <linux/input.h> | 69 | #include <linux/input.h> |
diff --git a/drivers/input/keyboard/pxa27x_keyboard.c b/drivers/input/keyboard/pxa27x_keyboard.c deleted file mode 100644 index bdd64ee4c5c8..000000000000 --- a/drivers/input/keyboard/pxa27x_keyboard.c +++ /dev/null | |||
@@ -1,274 +0,0 @@ | |||
1 | /* | ||
2 | * linux/drivers/input/keyboard/pxa27x_keyboard.c | ||
3 | * | ||
4 | * Driver for the pxa27x matrix keyboard controller. | ||
5 | * | ||
6 | * Created: Feb 22, 2007 | ||
7 | * Author: Rodolfo Giometti <giometti@linux.it> | ||
8 | * | ||
9 | * Based on a previous implementations by Kevin O'Connor | ||
10 | * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and | ||
11 | * on some suggestions by Nicolas Pitre <nico@cam.org>. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/input.h> | ||
24 | #include <linux/device.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/clk.h> | ||
27 | #include <linux/err.h> | ||
28 | |||
29 | #include <asm/mach-types.h> | ||
30 | #include <asm/mach/arch.h> | ||
31 | #include <asm/mach/map.h> | ||
32 | |||
33 | #include <asm/arch/hardware.h> | ||
34 | #include <asm/arch/pxa-regs.h> | ||
35 | #include <asm/arch/irqs.h> | ||
36 | #include <asm/arch/pxa27x_keyboard.h> | ||
37 | |||
38 | #define DRIVER_NAME "pxa27x-keyboard" | ||
39 | |||
40 | #define KPASMKP(col) (col/2 == 0 ? KPASMKP0 : \ | ||
41 | col/2 == 1 ? KPASMKP1 : \ | ||
42 | col/2 == 2 ? KPASMKP2 : KPASMKP3) | ||
43 | #define KPASMKPx_MKC(row, col) (1 << (row + 16 * (col % 2))) | ||
44 | |||
45 | static struct clk *pxakbd_clk; | ||
46 | |||
47 | static irqreturn_t pxakbd_irq_handler(int irq, void *dev_id) | ||
48 | { | ||
49 | struct platform_device *pdev = dev_id; | ||
50 | struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data; | ||
51 | struct input_dev *input_dev = platform_get_drvdata(pdev); | ||
52 | unsigned long kpc = KPC; | ||
53 | int p, row, col, rel; | ||
54 | |||
55 | if (kpc & KPC_DI) { | ||
56 | unsigned long kpdk = KPDK; | ||
57 | |||
58 | if (!(kpdk & KPDK_DKP)) { | ||
59 | /* better luck next time */ | ||
60 | } else if (kpc & KPC_REE0) { | ||
61 | unsigned long kprec = KPREC; | ||
62 | KPREC = 0x7f; | ||
63 | |||
64 | if (kprec & KPREC_OF0) | ||
65 | rel = (kprec & 0xff) + 0x7f; | ||
66 | else if (kprec & KPREC_UF0) | ||
67 | rel = (kprec & 0xff) - 0x7f - 0xff; | ||
68 | else | ||
69 | rel = (kprec & 0xff) - 0x7f; | ||
70 | |||
71 | if (rel) { | ||
72 | input_report_rel(input_dev, REL_WHEEL, rel); | ||
73 | input_sync(input_dev); | ||
74 | } | ||
75 | } | ||
76 | } | ||
77 | |||
78 | if (kpc & KPC_MI) { | ||
79 | /* report the status of every button */ | ||
80 | for (row = 0; row < pdata->nr_rows; row++) { | ||
81 | for (col = 0; col < pdata->nr_cols; col++) { | ||
82 | p = KPASMKP(col) & KPASMKPx_MKC(row, col) ? | ||
83 | 1 : 0; | ||
84 | pr_debug("keycode %x - pressed %x\n", | ||
85 | pdata->keycodes[row][col], p); | ||
86 | input_report_key(input_dev, | ||
87 | pdata->keycodes[row][col], p); | ||
88 | } | ||
89 | } | ||
90 | input_sync(input_dev); | ||
91 | } | ||
92 | |||
93 | return IRQ_HANDLED; | ||
94 | } | ||
95 | |||
96 | static int pxakbd_open(struct input_dev *dev) | ||
97 | { | ||
98 | /* Set keypad control register */ | ||
99 | KPC |= (KPC_ASACT | | ||
100 | KPC_MS_ALL | | ||
101 | (2 << 6) | KPC_REE0 | KPC_DK_DEB_SEL | | ||
102 | KPC_ME | KPC_MIE | KPC_DE | KPC_DIE); | ||
103 | |||
104 | KPC &= ~KPC_AS; /* disable automatic scan */ | ||
105 | KPC &= ~KPC_IMKP; /* do not ignore multiple keypresses */ | ||
106 | |||
107 | /* Set rotary count to mid-point value */ | ||
108 | KPREC = 0x7F; | ||
109 | |||
110 | /* Enable unit clock */ | ||
111 | clk_enable(pxakbd_clk); | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static void pxakbd_close(struct input_dev *dev) | ||
117 | { | ||
118 | /* Disable clock unit */ | ||
119 | clk_disable(pxakbd_clk); | ||
120 | } | ||
121 | |||
122 | #ifdef CONFIG_PM | ||
123 | static int pxakbd_suspend(struct platform_device *pdev, pm_message_t state) | ||
124 | { | ||
125 | struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data; | ||
126 | |||
127 | /* Save controller status */ | ||
128 | pdata->reg_kpc = KPC; | ||
129 | pdata->reg_kprec = KPREC; | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static int pxakbd_resume(struct platform_device *pdev) | ||
135 | { | ||
136 | struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data; | ||
137 | struct input_dev *input_dev = platform_get_drvdata(pdev); | ||
138 | |||
139 | mutex_lock(&input_dev->mutex); | ||
140 | |||
141 | if (input_dev->users) { | ||
142 | /* Restore controller status */ | ||
143 | KPC = pdata->reg_kpc; | ||
144 | KPREC = pdata->reg_kprec; | ||
145 | |||
146 | /* Enable unit clock */ | ||
147 | clk_disable(pxakbd_clk); | ||
148 | clk_enable(pxakbd_clk); | ||
149 | } | ||
150 | |||
151 | mutex_unlock(&input_dev->mutex); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | #else | ||
156 | #define pxakbd_suspend NULL | ||
157 | #define pxakbd_resume NULL | ||
158 | #endif | ||
159 | |||
160 | static int __devinit pxakbd_probe(struct platform_device *pdev) | ||
161 | { | ||
162 | struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data; | ||
163 | struct input_dev *input_dev; | ||
164 | int i, row, col, error; | ||
165 | |||
166 | pxakbd_clk = clk_get(&pdev->dev, "KBDCLK"); | ||
167 | if (IS_ERR(pxakbd_clk)) { | ||
168 | error = PTR_ERR(pxakbd_clk); | ||
169 | goto err_clk; | ||
170 | } | ||
171 | |||
172 | /* Create and register the input driver. */ | ||
173 | input_dev = input_allocate_device(); | ||
174 | if (!input_dev) { | ||
175 | printk(KERN_ERR "Cannot request keypad device\n"); | ||
176 | error = -ENOMEM; | ||
177 | goto err_alloc; | ||
178 | } | ||
179 | |||
180 | input_dev->name = DRIVER_NAME; | ||
181 | input_dev->id.bustype = BUS_HOST; | ||
182 | input_dev->open = pxakbd_open; | ||
183 | input_dev->close = pxakbd_close; | ||
184 | input_dev->dev.parent = &pdev->dev; | ||
185 | |||
186 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | | ||
187 | BIT_MASK(EV_REL); | ||
188 | input_dev->relbit[BIT_WORD(REL_WHEEL)] = BIT_MASK(REL_WHEEL); | ||
189 | for (row = 0; row < pdata->nr_rows; row++) { | ||
190 | for (col = 0; col < pdata->nr_cols; col++) { | ||
191 | int code = pdata->keycodes[row][col]; | ||
192 | if (code > 0) | ||
193 | set_bit(code, input_dev->keybit); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | error = request_irq(IRQ_KEYPAD, pxakbd_irq_handler, IRQF_DISABLED, | ||
198 | DRIVER_NAME, pdev); | ||
199 | if (error) { | ||
200 | printk(KERN_ERR "Cannot request keypad IRQ\n"); | ||
201 | goto err_free_dev; | ||
202 | } | ||
203 | |||
204 | platform_set_drvdata(pdev, input_dev); | ||
205 | |||
206 | /* Register the input device */ | ||
207 | error = input_register_device(input_dev); | ||
208 | if (error) | ||
209 | goto err_free_irq; | ||
210 | |||
211 | /* Setup GPIOs. */ | ||
212 | for (i = 0; i < pdata->nr_rows + pdata->nr_cols; i++) | ||
213 | pxa_gpio_mode(pdata->gpio_modes[i]); | ||
214 | |||
215 | /* | ||
216 | * Store rows/cols info into keyboard registers. | ||
217 | */ | ||
218 | |||
219 | KPC |= (pdata->nr_rows - 1) << 26; | ||
220 | KPC |= (pdata->nr_cols - 1) << 23; | ||
221 | |||
222 | for (col = 0; col < pdata->nr_cols; col++) | ||
223 | KPC |= KPC_MS0 << col; | ||
224 | |||
225 | return 0; | ||
226 | |||
227 | err_free_irq: | ||
228 | platform_set_drvdata(pdev, NULL); | ||
229 | free_irq(IRQ_KEYPAD, pdev); | ||
230 | err_free_dev: | ||
231 | input_free_device(input_dev); | ||
232 | err_alloc: | ||
233 | clk_put(pxakbd_clk); | ||
234 | err_clk: | ||
235 | return error; | ||
236 | } | ||
237 | |||
238 | static int __devexit pxakbd_remove(struct platform_device *pdev) | ||
239 | { | ||
240 | struct input_dev *input_dev = platform_get_drvdata(pdev); | ||
241 | |||
242 | input_unregister_device(input_dev); | ||
243 | free_irq(IRQ_KEYPAD, pdev); | ||
244 | clk_put(pxakbd_clk); | ||
245 | platform_set_drvdata(pdev, NULL); | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | static struct platform_driver pxakbd_driver = { | ||
251 | .probe = pxakbd_probe, | ||
252 | .remove = __devexit_p(pxakbd_remove), | ||
253 | .suspend = pxakbd_suspend, | ||
254 | .resume = pxakbd_resume, | ||
255 | .driver = { | ||
256 | .name = DRIVER_NAME, | ||
257 | }, | ||
258 | }; | ||
259 | |||
260 | static int __init pxakbd_init(void) | ||
261 | { | ||
262 | return platform_driver_register(&pxakbd_driver); | ||
263 | } | ||
264 | |||
265 | static void __exit pxakbd_exit(void) | ||
266 | { | ||
267 | platform_driver_unregister(&pxakbd_driver); | ||
268 | } | ||
269 | |||
270 | module_init(pxakbd_init); | ||
271 | module_exit(pxakbd_exit); | ||
272 | |||
273 | MODULE_DESCRIPTION("PXA27x Matrix Keyboard Driver"); | ||
274 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c new file mode 100644 index 000000000000..6224c2fb3b65 --- /dev/null +++ b/drivers/input/keyboard/pxa27x_keypad.c | |||
@@ -0,0 +1,572 @@ | |||
1 | /* | ||
2 | * linux/drivers/input/keyboard/pxa27x_keypad.c | ||
3 | * | ||
4 | * Driver for the pxa27x matrix keyboard controller. | ||
5 | * | ||
6 | * Created: Feb 22, 2007 | ||
7 | * Author: Rodolfo Giometti <giometti@linux.it> | ||
8 | * | ||
9 | * Based on a previous implementations by Kevin O'Connor | ||
10 | * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and | ||
11 | * on some suggestions by Nicolas Pitre <nico@cam.org>. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/input.h> | ||
24 | #include <linux/device.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/clk.h> | ||
27 | #include <linux/err.h> | ||
28 | |||
29 | #include <asm/mach-types.h> | ||
30 | #include <asm/mach/arch.h> | ||
31 | #include <asm/mach/map.h> | ||
32 | |||
33 | #include <asm/arch/hardware.h> | ||
34 | #include <asm/arch/pxa27x_keypad.h> | ||
35 | |||
36 | /* | ||
37 | * Keypad Controller registers | ||
38 | */ | ||
39 | #define KPC 0x0000 /* Keypad Control register */ | ||
40 | #define KPDK 0x0008 /* Keypad Direct Key register */ | ||
41 | #define KPREC 0x0010 /* Keypad Rotary Encoder register */ | ||
42 | #define KPMK 0x0018 /* Keypad Matrix Key register */ | ||
43 | #define KPAS 0x0020 /* Keypad Automatic Scan register */ | ||
44 | |||
45 | /* Keypad Automatic Scan Multiple Key Presser register 0-3 */ | ||
46 | #define KPASMKP0 0x0028 | ||
47 | #define KPASMKP1 0x0030 | ||
48 | #define KPASMKP2 0x0038 | ||
49 | #define KPASMKP3 0x0040 | ||
50 | #define KPKDI 0x0048 | ||
51 | |||
52 | /* bit definitions */ | ||
53 | #define KPC_MKRN(n) ((((n) & 0x7) - 1) << 26) /* matrix key row number */ | ||
54 | #define KPC_MKCN(n) ((((n) & 0x7) - 1) << 23) /* matrix key column number */ | ||
55 | #define KPC_DKN(n) ((((n) & 0x7) - 1) << 6) /* direct key number */ | ||
56 | |||
57 | #define KPC_AS (0x1 << 30) /* Automatic Scan bit */ | ||
58 | #define KPC_ASACT (0x1 << 29) /* Automatic Scan on Activity */ | ||
59 | #define KPC_MI (0x1 << 22) /* Matrix interrupt bit */ | ||
60 | #define KPC_IMKP (0x1 << 21) /* Ignore Multiple Key Press */ | ||
61 | |||
62 | #define KPC_MS(n) (0x1 << (13 + (n))) /* Matrix scan line 'n' */ | ||
63 | #define KPC_MS_ALL (0xff << 13) | ||
64 | |||
65 | #define KPC_ME (0x1 << 12) /* Matrix Keypad Enable */ | ||
66 | #define KPC_MIE (0x1 << 11) /* Matrix Interrupt Enable */ | ||
67 | #define KPC_DK_DEB_SEL (0x1 << 9) /* Direct Keypad Debounce Select */ | ||
68 | #define KPC_DI (0x1 << 5) /* Direct key interrupt bit */ | ||
69 | #define KPC_RE_ZERO_DEB (0x1 << 4) /* Rotary Encoder Zero Debounce */ | ||
70 | #define KPC_REE1 (0x1 << 3) /* Rotary Encoder1 Enable */ | ||
71 | #define KPC_REE0 (0x1 << 2) /* Rotary Encoder0 Enable */ | ||
72 | #define KPC_DE (0x1 << 1) /* Direct Keypad Enable */ | ||
73 | #define KPC_DIE (0x1 << 0) /* Direct Keypad interrupt Enable */ | ||
74 | |||
75 | #define KPDK_DKP (0x1 << 31) | ||
76 | #define KPDK_DK(n) ((n) & 0xff) | ||
77 | |||
78 | #define KPREC_OF1 (0x1 << 31) | ||
79 | #define kPREC_UF1 (0x1 << 30) | ||
80 | #define KPREC_OF0 (0x1 << 15) | ||
81 | #define KPREC_UF0 (0x1 << 14) | ||
82 | |||
83 | #define KPREC_RECOUNT0(n) ((n) & 0xff) | ||
84 | #define KPREC_RECOUNT1(n) (((n) >> 16) & 0xff) | ||
85 | |||
86 | #define KPMK_MKP (0x1 << 31) | ||
87 | #define KPAS_SO (0x1 << 31) | ||
88 | #define KPASMKPx_SO (0x1 << 31) | ||
89 | |||
90 | #define KPAS_MUKP(n) (((n) >> 26) & 0x1f) | ||
91 | #define KPAS_RP(n) (((n) >> 4) & 0xf) | ||
92 | #define KPAS_CP(n) ((n) & 0xf) | ||
93 | |||
94 | #define KPASMKP_MKC_MASK (0xff) | ||
95 | |||
96 | #define keypad_readl(off) __raw_readl(keypad->mmio_base + (off)) | ||
97 | #define keypad_writel(off, v) __raw_writel((v), keypad->mmio_base + (off)) | ||
98 | |||
99 | #define MAX_MATRIX_KEY_NUM (8 * 8) | ||
100 | |||
101 | struct pxa27x_keypad { | ||
102 | struct pxa27x_keypad_platform_data *pdata; | ||
103 | |||
104 | struct clk *clk; | ||
105 | struct input_dev *input_dev; | ||
106 | void __iomem *mmio_base; | ||
107 | |||
108 | /* matrix key code map */ | ||
109 | unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM]; | ||
110 | |||
111 | /* state row bits of each column scan */ | ||
112 | uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS]; | ||
113 | uint32_t direct_key_state; | ||
114 | |||
115 | unsigned int direct_key_mask; | ||
116 | |||
117 | int rotary_rel_code[2]; | ||
118 | int rotary_up_key[2]; | ||
119 | int rotary_down_key[2]; | ||
120 | }; | ||
121 | |||
122 | static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) | ||
123 | { | ||
124 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | ||
125 | struct input_dev *input_dev = keypad->input_dev; | ||
126 | unsigned int *key; | ||
127 | int i; | ||
128 | |||
129 | key = &pdata->matrix_key_map[0]; | ||
130 | for (i = 0; i < pdata->matrix_key_map_size; i++, key++) { | ||
131 | int row = ((*key) >> 28) & 0xf; | ||
132 | int col = ((*key) >> 24) & 0xf; | ||
133 | int code = (*key) & 0xffffff; | ||
134 | |||
135 | keypad->matrix_keycodes[(row << 3) + col] = code; | ||
136 | set_bit(code, input_dev->keybit); | ||
137 | } | ||
138 | |||
139 | keypad->rotary_up_key[0] = pdata->rotary0_up_key; | ||
140 | keypad->rotary_up_key[1] = pdata->rotary1_up_key; | ||
141 | keypad->rotary_down_key[0] = pdata->rotary0_down_key; | ||
142 | keypad->rotary_down_key[1] = pdata->rotary1_down_key; | ||
143 | keypad->rotary_rel_code[0] = pdata->rotary0_rel_code; | ||
144 | keypad->rotary_rel_code[1] = pdata->rotary1_rel_code; | ||
145 | |||
146 | if (pdata->rotary0_up_key && pdata->rotary0_down_key) { | ||
147 | set_bit(pdata->rotary0_up_key, input_dev->keybit); | ||
148 | set_bit(pdata->rotary0_down_key, input_dev->keybit); | ||
149 | } else | ||
150 | set_bit(pdata->rotary0_rel_code, input_dev->relbit); | ||
151 | |||
152 | if (pdata->rotary1_up_key && pdata->rotary1_down_key) { | ||
153 | set_bit(pdata->rotary1_up_key, input_dev->keybit); | ||
154 | set_bit(pdata->rotary1_down_key, input_dev->keybit); | ||
155 | } else | ||
156 | set_bit(pdata->rotary1_rel_code, input_dev->relbit); | ||
157 | } | ||
158 | |||
159 | static inline unsigned int lookup_matrix_keycode( | ||
160 | struct pxa27x_keypad *keypad, int row, int col) | ||
161 | { | ||
162 | return keypad->matrix_keycodes[(row << 3) + col]; | ||
163 | } | ||
164 | |||
165 | static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) | ||
166 | { | ||
167 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | ||
168 | int row, col, num_keys_pressed = 0; | ||
169 | uint32_t new_state[MAX_MATRIX_KEY_COLS]; | ||
170 | uint32_t kpas = keypad_readl(KPAS); | ||
171 | |||
172 | num_keys_pressed = KPAS_MUKP(kpas); | ||
173 | |||
174 | memset(new_state, 0, sizeof(new_state)); | ||
175 | |||
176 | if (num_keys_pressed == 0) | ||
177 | goto scan; | ||
178 | |||
179 | if (num_keys_pressed == 1) { | ||
180 | col = KPAS_CP(kpas); | ||
181 | row = KPAS_RP(kpas); | ||
182 | |||
183 | /* if invalid row/col, treat as no key pressed */ | ||
184 | if (col >= pdata->matrix_key_cols || | ||
185 | row >= pdata->matrix_key_rows) | ||
186 | goto scan; | ||
187 | |||
188 | new_state[col] = (1 << row); | ||
189 | goto scan; | ||
190 | } | ||
191 | |||
192 | if (num_keys_pressed > 1) { | ||
193 | uint32_t kpasmkp0 = keypad_readl(KPASMKP0); | ||
194 | uint32_t kpasmkp1 = keypad_readl(KPASMKP1); | ||
195 | uint32_t kpasmkp2 = keypad_readl(KPASMKP2); | ||
196 | uint32_t kpasmkp3 = keypad_readl(KPASMKP3); | ||
197 | |||
198 | new_state[0] = kpasmkp0 & KPASMKP_MKC_MASK; | ||
199 | new_state[1] = (kpasmkp0 >> 16) & KPASMKP_MKC_MASK; | ||
200 | new_state[2] = kpasmkp1 & KPASMKP_MKC_MASK; | ||
201 | new_state[3] = (kpasmkp1 >> 16) & KPASMKP_MKC_MASK; | ||
202 | new_state[4] = kpasmkp2 & KPASMKP_MKC_MASK; | ||
203 | new_state[5] = (kpasmkp2 >> 16) & KPASMKP_MKC_MASK; | ||
204 | new_state[6] = kpasmkp3 & KPASMKP_MKC_MASK; | ||
205 | new_state[7] = (kpasmkp3 >> 16) & KPASMKP_MKC_MASK; | ||
206 | } | ||
207 | scan: | ||
208 | for (col = 0; col < pdata->matrix_key_cols; col++) { | ||
209 | uint32_t bits_changed; | ||
210 | |||
211 | bits_changed = keypad->matrix_key_state[col] ^ new_state[col]; | ||
212 | if (bits_changed == 0) | ||
213 | continue; | ||
214 | |||
215 | for (row = 0; row < pdata->matrix_key_rows; row++) { | ||
216 | if ((bits_changed & (1 << row)) == 0) | ||
217 | continue; | ||
218 | |||
219 | input_report_key(keypad->input_dev, | ||
220 | lookup_matrix_keycode(keypad, row, col), | ||
221 | new_state[col] & (1 << row)); | ||
222 | } | ||
223 | } | ||
224 | input_sync(keypad->input_dev); | ||
225 | memcpy(keypad->matrix_key_state, new_state, sizeof(new_state)); | ||
226 | } | ||
227 | |||
228 | #define DEFAULT_KPREC (0x007f007f) | ||
229 | |||
230 | static inline int rotary_delta(uint32_t kprec) | ||
231 | { | ||
232 | if (kprec & KPREC_OF0) | ||
233 | return (kprec & 0xff) + 0x7f; | ||
234 | else if (kprec & KPREC_UF0) | ||
235 | return (kprec & 0xff) - 0x7f - 0xff; | ||
236 | else | ||
237 | return (kprec & 0xff) - 0x7f; | ||
238 | } | ||
239 | |||
240 | static void report_rotary_event(struct pxa27x_keypad *keypad, int r, int delta) | ||
241 | { | ||
242 | struct input_dev *dev = keypad->input_dev; | ||
243 | |||
244 | if (delta == 0) | ||
245 | return; | ||
246 | |||
247 | if (keypad->rotary_up_key[r] && keypad->rotary_down_key[r]) { | ||
248 | int keycode = (delta > 0) ? keypad->rotary_up_key[r] : | ||
249 | keypad->rotary_down_key[r]; | ||
250 | |||
251 | /* simulate a press-n-release */ | ||
252 | input_report_key(dev, keycode, 1); | ||
253 | input_sync(dev); | ||
254 | input_report_key(dev, keycode, 0); | ||
255 | input_sync(dev); | ||
256 | } else { | ||
257 | input_report_rel(dev, keypad->rotary_rel_code[r], delta); | ||
258 | input_sync(dev); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad) | ||
263 | { | ||
264 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | ||
265 | uint32_t kprec; | ||
266 | |||
267 | /* read and reset to default count value */ | ||
268 | kprec = keypad_readl(KPREC); | ||
269 | keypad_writel(KPREC, DEFAULT_KPREC); | ||
270 | |||
271 | if (pdata->enable_rotary0) | ||
272 | report_rotary_event(keypad, 0, rotary_delta(kprec)); | ||
273 | |||
274 | if (pdata->enable_rotary1) | ||
275 | report_rotary_event(keypad, 1, rotary_delta(kprec >> 16)); | ||
276 | } | ||
277 | |||
278 | static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | ||
279 | { | ||
280 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | ||
281 | unsigned int new_state; | ||
282 | uint32_t kpdk, bits_changed; | ||
283 | int i; | ||
284 | |||
285 | kpdk = keypad_readl(KPDK); | ||
286 | |||
287 | if (pdata->enable_rotary0 || pdata->enable_rotary1) | ||
288 | pxa27x_keypad_scan_rotary(keypad); | ||
289 | |||
290 | if (pdata->direct_key_map == NULL) | ||
291 | return; | ||
292 | |||
293 | new_state = KPDK_DK(kpdk) & keypad->direct_key_mask; | ||
294 | bits_changed = keypad->direct_key_state ^ new_state; | ||
295 | |||
296 | if (bits_changed == 0) | ||
297 | return; | ||
298 | |||
299 | for (i = 0; i < pdata->direct_key_num; i++) { | ||
300 | if (bits_changed & (1 << i)) | ||
301 | input_report_key(keypad->input_dev, | ||
302 | pdata->direct_key_map[i], | ||
303 | (new_state & (1 << i))); | ||
304 | } | ||
305 | input_sync(keypad->input_dev); | ||
306 | keypad->direct_key_state = new_state; | ||
307 | } | ||
308 | |||
309 | static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id) | ||
310 | { | ||
311 | struct pxa27x_keypad *keypad = dev_id; | ||
312 | unsigned long kpc = keypad_readl(KPC); | ||
313 | |||
314 | if (kpc & KPC_DI) | ||
315 | pxa27x_keypad_scan_direct(keypad); | ||
316 | |||
317 | if (kpc & KPC_MI) | ||
318 | pxa27x_keypad_scan_matrix(keypad); | ||
319 | |||
320 | return IRQ_HANDLED; | ||
321 | } | ||
322 | |||
323 | static void pxa27x_keypad_config(struct pxa27x_keypad *keypad) | ||
324 | { | ||
325 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | ||
326 | unsigned int mask = 0, direct_key_num = 0; | ||
327 | unsigned long kpc = 0; | ||
328 | |||
329 | /* enable matrix keys with automatic scan */ | ||
330 | if (pdata->matrix_key_rows && pdata->matrix_key_cols) { | ||
331 | kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL; | ||
332 | kpc |= KPC_MKRN(pdata->matrix_key_rows) | | ||
333 | KPC_MKCN(pdata->matrix_key_cols); | ||
334 | } | ||
335 | |||
336 | /* enable rotary key, debounce interval same as direct keys */ | ||
337 | if (pdata->enable_rotary0) { | ||
338 | mask |= 0x03; | ||
339 | direct_key_num = 2; | ||
340 | kpc |= KPC_REE0; | ||
341 | } | ||
342 | |||
343 | if (pdata->enable_rotary1) { | ||
344 | mask |= 0x0c; | ||
345 | direct_key_num = 4; | ||
346 | kpc |= KPC_REE1; | ||
347 | } | ||
348 | |||
349 | if (pdata->direct_key_num > direct_key_num) | ||
350 | direct_key_num = pdata->direct_key_num; | ||
351 | |||
352 | keypad->direct_key_mask = ((2 << direct_key_num) - 1) & ~mask; | ||
353 | |||
354 | /* enable direct key */ | ||
355 | if (direct_key_num) | ||
356 | kpc |= KPC_DE | KPC_DIE | KPC_DKN(direct_key_num); | ||
357 | |||
358 | keypad_writel(KPC, kpc | KPC_RE_ZERO_DEB); | ||
359 | keypad_writel(KPREC, DEFAULT_KPREC); | ||
360 | keypad_writel(KPKDI, pdata->debounce_interval); | ||
361 | } | ||
362 | |||
363 | static int pxa27x_keypad_open(struct input_dev *dev) | ||
364 | { | ||
365 | struct pxa27x_keypad *keypad = input_get_drvdata(dev); | ||
366 | |||
367 | /* Enable unit clock */ | ||
368 | clk_enable(keypad->clk); | ||
369 | pxa27x_keypad_config(keypad); | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static void pxa27x_keypad_close(struct input_dev *dev) | ||
375 | { | ||
376 | struct pxa27x_keypad *keypad = input_get_drvdata(dev); | ||
377 | |||
378 | /* Disable clock unit */ | ||
379 | clk_disable(keypad->clk); | ||
380 | } | ||
381 | |||
382 | #ifdef CONFIG_PM | ||
383 | static int pxa27x_keypad_suspend(struct platform_device *pdev, pm_message_t state) | ||
384 | { | ||
385 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | ||
386 | |||
387 | clk_disable(keypad->clk); | ||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | static int pxa27x_keypad_resume(struct platform_device *pdev) | ||
392 | { | ||
393 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | ||
394 | struct input_dev *input_dev = keypad->input_dev; | ||
395 | |||
396 | mutex_lock(&input_dev->mutex); | ||
397 | |||
398 | if (input_dev->users) { | ||
399 | /* Enable unit clock */ | ||
400 | clk_enable(keypad->clk); | ||
401 | pxa27x_keypad_config(keypad); | ||
402 | } | ||
403 | |||
404 | mutex_unlock(&input_dev->mutex); | ||
405 | |||
406 | return 0; | ||
407 | } | ||
408 | #else | ||
409 | #define pxa27x_keypad_suspend NULL | ||
410 | #define pxa27x_keypad_resume NULL | ||
411 | #endif | ||
412 | |||
413 | #define res_size(res) ((res)->end - (res)->start + 1) | ||
414 | |||
415 | static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | ||
416 | { | ||
417 | struct pxa27x_keypad *keypad; | ||
418 | struct input_dev *input_dev; | ||
419 | struct resource *res; | ||
420 | int irq, error; | ||
421 | |||
422 | keypad = kzalloc(sizeof(struct pxa27x_keypad), GFP_KERNEL); | ||
423 | if (keypad == NULL) { | ||
424 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
425 | return -ENOMEM; | ||
426 | } | ||
427 | |||
428 | keypad->pdata = pdev->dev.platform_data; | ||
429 | if (keypad->pdata == NULL) { | ||
430 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
431 | error = -EINVAL; | ||
432 | goto failed_free; | ||
433 | } | ||
434 | |||
435 | irq = platform_get_irq(pdev, 0); | ||
436 | if (irq < 0) { | ||
437 | dev_err(&pdev->dev, "failed to get keypad irq\n"); | ||
438 | error = -ENXIO; | ||
439 | goto failed_free; | ||
440 | } | ||
441 | |||
442 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
443 | if (res == NULL) { | ||
444 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | ||
445 | error = -ENXIO; | ||
446 | goto failed_free; | ||
447 | } | ||
448 | |||
449 | res = request_mem_region(res->start, res_size(res), pdev->name); | ||
450 | if (res == NULL) { | ||
451 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
452 | error = -EBUSY; | ||
453 | goto failed_free; | ||
454 | } | ||
455 | |||
456 | keypad->mmio_base = ioremap(res->start, res_size(res)); | ||
457 | if (keypad->mmio_base == NULL) { | ||
458 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
459 | error = -ENXIO; | ||
460 | goto failed_free_mem; | ||
461 | } | ||
462 | |||
463 | keypad->clk = clk_get(&pdev->dev, "KBDCLK"); | ||
464 | if (IS_ERR(keypad->clk)) { | ||
465 | dev_err(&pdev->dev, "failed to get keypad clock\n"); | ||
466 | error = PTR_ERR(keypad->clk); | ||
467 | goto failed_free_io; | ||
468 | } | ||
469 | |||
470 | /* Create and register the input driver. */ | ||
471 | input_dev = input_allocate_device(); | ||
472 | if (!input_dev) { | ||
473 | dev_err(&pdev->dev, "failed to allocate input device\n"); | ||
474 | error = -ENOMEM; | ||
475 | goto failed_put_clk; | ||
476 | } | ||
477 | |||
478 | input_dev->name = pdev->name; | ||
479 | input_dev->id.bustype = BUS_HOST; | ||
480 | input_dev->open = pxa27x_keypad_open; | ||
481 | input_dev->close = pxa27x_keypad_close; | ||
482 | input_dev->dev.parent = &pdev->dev; | ||
483 | |||
484 | keypad->input_dev = input_dev; | ||
485 | input_set_drvdata(input_dev, keypad); | ||
486 | |||
487 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | | ||
488 | BIT_MASK(EV_REL); | ||
489 | |||
490 | pxa27x_keypad_build_keycode(keypad); | ||
491 | platform_set_drvdata(pdev, keypad); | ||
492 | |||
493 | error = request_irq(irq, pxa27x_keypad_irq_handler, IRQF_DISABLED, | ||
494 | pdev->name, keypad); | ||
495 | if (error) { | ||
496 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
497 | goto failed_free_dev; | ||
498 | } | ||
499 | |||
500 | /* Register the input device */ | ||
501 | error = input_register_device(input_dev); | ||
502 | if (error) { | ||
503 | dev_err(&pdev->dev, "failed to register input device\n"); | ||
504 | goto failed_free_irq; | ||
505 | } | ||
506 | |||
507 | return 0; | ||
508 | |||
509 | failed_free_irq: | ||
510 | free_irq(irq, pdev); | ||
511 | platform_set_drvdata(pdev, NULL); | ||
512 | failed_free_dev: | ||
513 | input_free_device(input_dev); | ||
514 | failed_put_clk: | ||
515 | clk_put(keypad->clk); | ||
516 | failed_free_io: | ||
517 | iounmap(keypad->mmio_base); | ||
518 | failed_free_mem: | ||
519 | release_mem_region(res->start, res_size(res)); | ||
520 | failed_free: | ||
521 | kfree(keypad); | ||
522 | return error; | ||
523 | } | ||
524 | |||
525 | static int __devexit pxa27x_keypad_remove(struct platform_device *pdev) | ||
526 | { | ||
527 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | ||
528 | struct resource *res; | ||
529 | |||
530 | free_irq(platform_get_irq(pdev, 0), pdev); | ||
531 | |||
532 | clk_disable(keypad->clk); | ||
533 | clk_put(keypad->clk); | ||
534 | |||
535 | input_unregister_device(keypad->input_dev); | ||
536 | input_free_device(keypad->input_dev); | ||
537 | |||
538 | iounmap(keypad->mmio_base); | ||
539 | |||
540 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
541 | release_mem_region(res->start, res_size(res)); | ||
542 | |||
543 | platform_set_drvdata(pdev, NULL); | ||
544 | kfree(keypad); | ||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | static struct platform_driver pxa27x_keypad_driver = { | ||
549 | .probe = pxa27x_keypad_probe, | ||
550 | .remove = __devexit_p(pxa27x_keypad_remove), | ||
551 | .suspend = pxa27x_keypad_suspend, | ||
552 | .resume = pxa27x_keypad_resume, | ||
553 | .driver = { | ||
554 | .name = "pxa27x-keypad", | ||
555 | }, | ||
556 | }; | ||
557 | |||
558 | static int __init pxa27x_keypad_init(void) | ||
559 | { | ||
560 | return platform_driver_register(&pxa27x_keypad_driver); | ||
561 | } | ||
562 | |||
563 | static void __exit pxa27x_keypad_exit(void) | ||
564 | { | ||
565 | platform_driver_unregister(&pxa27x_keypad_driver); | ||
566 | } | ||
567 | |||
568 | module_init(pxa27x_keypad_init); | ||
569 | module_exit(pxa27x_keypad_exit); | ||
570 | |||
571 | MODULE_DESCRIPTION("PXA27x Keypad Controller Driver"); | ||
572 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c new file mode 100644 index 000000000000..3884d1e3f070 --- /dev/null +++ b/drivers/input/keyboard/tosakbd.c | |||
@@ -0,0 +1,415 @@ | |||
1 | /* | ||
2 | * Keyboard driver for Sharp Tosa models (SL-6000x) | ||
3 | * | ||
4 | * Copyright (c) 2005 Dirk Opfer | ||
5 | * Copyright (c) 2007 Dmitry Baryshkov | ||
6 | * | ||
7 | * Based on xtkbd.c/locomkbd.c/corgikbd.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/input.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | |||
22 | #include <asm/arch/gpio.h> | ||
23 | #include <asm/arch/tosa.h> | ||
24 | |||
25 | #define KB_ROWMASK(r) (1 << (r)) | ||
26 | #define SCANCODE(r, c) (((r)<<4) + (c) + 1) | ||
27 | #define NR_SCANCODES SCANCODE(TOSA_KEY_SENSE_NUM - 1, TOSA_KEY_STROBE_NUM - 1) + 1 | ||
28 | |||
29 | #define SCAN_INTERVAL (HZ/10) | ||
30 | |||
31 | #define KB_DISCHARGE_DELAY 10 | ||
32 | #define KB_ACTIVATE_DELAY 10 | ||
33 | |||
34 | static unsigned int tosakbd_keycode[NR_SCANCODES] = { | ||
35 | 0, | ||
36 | 0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, | ||
37 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
38 | KEY_Q, KEY_E, KEY_T, KEY_Y, 0, KEY_O, KEY_I, KEY_COMMA, | ||
39 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
40 | KEY_A, KEY_D, KEY_G, KEY_U, 0, KEY_L, KEY_ENTER, KEY_DOT, | ||
41 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
42 | KEY_Z, KEY_C, KEY_V, KEY_J, TOSA_KEY_ADDRESSBOOK, TOSA_KEY_CANCEL, TOSA_KEY_CENTER, TOSA_KEY_OK, | ||
43 | KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, 0, | ||
44 | KEY_S, KEY_R, KEY_B, KEY_N, TOSA_KEY_CALENDAR, TOSA_KEY_HOMEPAGE, KEY_LEFTCTRL, TOSA_KEY_LIGHT, | ||
45 | 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, | ||
46 | KEY_TAB, KEY_SLASH, KEY_H, KEY_M, TOSA_KEY_MENU, 0, KEY_UP, 0, | ||
47 | 0, 0, TOSA_KEY_FN, 0, 0, 0, 0, 0, | ||
48 | KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_RIGHT, | ||
49 | 0, 0, 0, | ||
50 | }; | ||
51 | |||
52 | struct tosakbd { | ||
53 | unsigned int keycode[ARRAY_SIZE(tosakbd_keycode)]; | ||
54 | struct input_dev *input; | ||
55 | |||
56 | spinlock_t lock; /* protect kbd scanning */ | ||
57 | struct timer_list timer; | ||
58 | }; | ||
59 | |||
60 | |||
61 | /* Helper functions for reading the keyboard matrix | ||
62 | * Note: We should really be using pxa_gpio_mode to alter GPDR but it | ||
63 | * requires a function call per GPIO bit which is excessive | ||
64 | * when we need to access 12 bits at once, multiple times. | ||
65 | * These functions must be called within local_irq_save()/local_irq_restore() | ||
66 | * or similar. | ||
67 | */ | ||
68 | #define GET_ROWS_STATUS(c) ((GPLR2 & TOSA_GPIO_ALL_SENSE_BIT) >> TOSA_GPIO_ALL_SENSE_RSHIFT) | ||
69 | |||
70 | static inline void tosakbd_discharge_all(void) | ||
71 | { | ||
72 | /* STROBE All HiZ */ | ||
73 | GPCR1 = TOSA_GPIO_HIGH_STROBE_BIT; | ||
74 | GPDR1 &= ~TOSA_GPIO_HIGH_STROBE_BIT; | ||
75 | GPCR2 = TOSA_GPIO_LOW_STROBE_BIT; | ||
76 | GPDR2 &= ~TOSA_GPIO_LOW_STROBE_BIT; | ||
77 | } | ||
78 | |||
79 | static inline void tosakbd_activate_all(void) | ||
80 | { | ||
81 | /* STROBE ALL -> High */ | ||
82 | GPSR1 = TOSA_GPIO_HIGH_STROBE_BIT; | ||
83 | GPDR1 |= TOSA_GPIO_HIGH_STROBE_BIT; | ||
84 | GPSR2 = TOSA_GPIO_LOW_STROBE_BIT; | ||
85 | GPDR2 |= TOSA_GPIO_LOW_STROBE_BIT; | ||
86 | |||
87 | udelay(KB_DISCHARGE_DELAY); | ||
88 | |||
89 | /* STATE CLEAR */ | ||
90 | GEDR2 |= TOSA_GPIO_ALL_SENSE_BIT; | ||
91 | } | ||
92 | |||
93 | static inline void tosakbd_activate_col(int col) | ||
94 | { | ||
95 | if (col <= 5) { | ||
96 | /* STROBE col -> High, not col -> HiZ */ | ||
97 | GPSR1 = TOSA_GPIO_STROBE_BIT(col); | ||
98 | GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); | ||
99 | } else { | ||
100 | /* STROBE col -> High, not col -> HiZ */ | ||
101 | GPSR2 = TOSA_GPIO_STROBE_BIT(col); | ||
102 | GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | static inline void tosakbd_reset_col(int col) | ||
107 | { | ||
108 | if (col <= 5) { | ||
109 | /* STROBE col -> Low */ | ||
110 | GPCR1 = TOSA_GPIO_STROBE_BIT(col); | ||
111 | /* STROBE col -> out, not col -> HiZ */ | ||
112 | GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); | ||
113 | } else { | ||
114 | /* STROBE col -> Low */ | ||
115 | GPCR2 = TOSA_GPIO_STROBE_BIT(col); | ||
116 | /* STROBE col -> out, not col -> HiZ */ | ||
117 | GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); | ||
118 | } | ||
119 | } | ||
120 | /* | ||
121 | * The tosa keyboard only generates interrupts when a key is pressed. | ||
122 | * So when a key is pressed, we enable a timer. This timer scans the | ||
123 | * keyboard, and this is how we detect when the key is released. | ||
124 | */ | ||
125 | |||
126 | /* Scan the hardware keyboard and push any changes up through the input layer */ | ||
127 | static void tosakbd_scankeyboard(struct platform_device *dev) | ||
128 | { | ||
129 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
130 | unsigned int row, col, rowd; | ||
131 | unsigned long flags; | ||
132 | unsigned int num_pressed = 0; | ||
133 | |||
134 | spin_lock_irqsave(&tosakbd->lock, flags); | ||
135 | |||
136 | for (col = 0; col < TOSA_KEY_STROBE_NUM; col++) { | ||
137 | /* | ||
138 | * Discharge the output driver capacitatance | ||
139 | * in the keyboard matrix. (Yes it is significant..) | ||
140 | */ | ||
141 | tosakbd_discharge_all(); | ||
142 | udelay(KB_DISCHARGE_DELAY); | ||
143 | |||
144 | tosakbd_activate_col(col); | ||
145 | udelay(KB_ACTIVATE_DELAY); | ||
146 | |||
147 | rowd = GET_ROWS_STATUS(col); | ||
148 | |||
149 | for (row = 0; row < TOSA_KEY_SENSE_NUM; row++) { | ||
150 | unsigned int scancode, pressed; | ||
151 | scancode = SCANCODE(row, col); | ||
152 | pressed = rowd & KB_ROWMASK(row); | ||
153 | |||
154 | if (pressed && !tosakbd->keycode[scancode]) | ||
155 | dev_warn(&dev->dev, | ||
156 | "unhandled scancode: 0x%02x\n", | ||
157 | scancode); | ||
158 | |||
159 | input_report_key(tosakbd->input, | ||
160 | tosakbd->keycode[scancode], | ||
161 | pressed); | ||
162 | if (pressed) | ||
163 | num_pressed++; | ||
164 | } | ||
165 | |||
166 | tosakbd_reset_col(col); | ||
167 | } | ||
168 | |||
169 | tosakbd_activate_all(); | ||
170 | |||
171 | input_sync(tosakbd->input); | ||
172 | |||
173 | /* if any keys are pressed, enable the timer */ | ||
174 | if (num_pressed) | ||
175 | mod_timer(&tosakbd->timer, jiffies + SCAN_INTERVAL); | ||
176 | |||
177 | spin_unlock_irqrestore(&tosakbd->lock, flags); | ||
178 | } | ||
179 | |||
180 | /* | ||
181 | * tosa keyboard interrupt handler. | ||
182 | */ | ||
183 | static irqreturn_t tosakbd_interrupt(int irq, void *__dev) | ||
184 | { | ||
185 | struct platform_device *dev = __dev; | ||
186 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
187 | |||
188 | if (!timer_pending(&tosakbd->timer)) { | ||
189 | /** wait chattering delay **/ | ||
190 | udelay(20); | ||
191 | tosakbd_scankeyboard(dev); | ||
192 | } | ||
193 | |||
194 | return IRQ_HANDLED; | ||
195 | } | ||
196 | |||
197 | /* | ||
198 | * tosa timer checking for released keys | ||
199 | */ | ||
200 | static void tosakbd_timer_callback(unsigned long __dev) | ||
201 | { | ||
202 | struct platform_device *dev = (struct platform_device *)__dev; | ||
203 | tosakbd_scankeyboard(dev); | ||
204 | } | ||
205 | |||
206 | #ifdef CONFIG_PM | ||
207 | static int tosakbd_suspend(struct platform_device *dev, pm_message_t state) | ||
208 | { | ||
209 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
210 | |||
211 | del_timer_sync(&tosakbd->timer); | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int tosakbd_resume(struct platform_device *dev) | ||
217 | { | ||
218 | tosakbd_scankeyboard(dev); | ||
219 | |||
220 | return 0; | ||
221 | } | ||
222 | #else | ||
223 | #define tosakbd_suspend NULL | ||
224 | #define tosakbd_resume NULL | ||
225 | #endif | ||
226 | |||
227 | static int __devinit tosakbd_probe(struct platform_device *pdev) { | ||
228 | |||
229 | int i; | ||
230 | struct tosakbd *tosakbd; | ||
231 | struct input_dev *input_dev; | ||
232 | int error; | ||
233 | |||
234 | tosakbd = kzalloc(sizeof(struct tosakbd), GFP_KERNEL); | ||
235 | if (!tosakbd) | ||
236 | return -ENOMEM; | ||
237 | |||
238 | input_dev = input_allocate_device(); | ||
239 | if (!input_dev) { | ||
240 | kfree(tosakbd); | ||
241 | return -ENOMEM; | ||
242 | } | ||
243 | |||
244 | platform_set_drvdata(pdev, tosakbd); | ||
245 | |||
246 | spin_lock_init(&tosakbd->lock); | ||
247 | |||
248 | /* Init Keyboard rescan timer */ | ||
249 | init_timer(&tosakbd->timer); | ||
250 | tosakbd->timer.function = tosakbd_timer_callback; | ||
251 | tosakbd->timer.data = (unsigned long) pdev; | ||
252 | |||
253 | tosakbd->input = input_dev; | ||
254 | |||
255 | input_set_drvdata(input_dev, tosakbd); | ||
256 | input_dev->name = "Tosa Keyboard"; | ||
257 | input_dev->phys = "tosakbd/input0"; | ||
258 | input_dev->dev.parent = &pdev->dev; | ||
259 | |||
260 | input_dev->id.bustype = BUS_HOST; | ||
261 | input_dev->id.vendor = 0x0001; | ||
262 | input_dev->id.product = 0x0001; | ||
263 | input_dev->id.version = 0x0100; | ||
264 | |||
265 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
266 | input_dev->keycode = tosakbd->keycode; | ||
267 | input_dev->keycodesize = sizeof(unsigned int); | ||
268 | input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode); | ||
269 | |||
270 | memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd_keycode)); | ||
271 | |||
272 | for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++) | ||
273 | __set_bit(tosakbd->keycode[i], input_dev->keybit); | ||
274 | clear_bit(0, input_dev->keybit); | ||
275 | |||
276 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ | ||
277 | for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { | ||
278 | int gpio = TOSA_GPIO_KEY_SENSE(i); | ||
279 | int irq; | ||
280 | error = gpio_request(gpio, "tosakbd"); | ||
281 | if (error < 0) { | ||
282 | printk(KERN_ERR "tosakbd: failed to request GPIO %d, " | ||
283 | " error %d\n", gpio, error); | ||
284 | goto fail; | ||
285 | } | ||
286 | |||
287 | error = gpio_direction_input(TOSA_GPIO_KEY_SENSE(i)); | ||
288 | if (error < 0) { | ||
289 | printk(KERN_ERR "tosakbd: failed to configure input" | ||
290 | " direction for GPIO %d, error %d\n", | ||
291 | gpio, error); | ||
292 | gpio_free(gpio); | ||
293 | goto fail; | ||
294 | } | ||
295 | |||
296 | irq = gpio_to_irq(gpio); | ||
297 | if (irq < 0) { | ||
298 | error = irq; | ||
299 | printk(KERN_ERR "gpio-keys: Unable to get irq number" | ||
300 | " for GPIO %d, error %d\n", | ||
301 | gpio, error); | ||
302 | gpio_free(gpio); | ||
303 | goto fail; | ||
304 | } | ||
305 | |||
306 | error = request_irq(irq, tosakbd_interrupt, | ||
307 | IRQF_DISABLED | IRQF_TRIGGER_RISING, | ||
308 | "tosakbd", pdev); | ||
309 | |||
310 | if (error) { | ||
311 | printk("tosakbd: Can't get IRQ: %d: error %d!\n", | ||
312 | irq, error); | ||
313 | gpio_free(gpio); | ||
314 | goto fail; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | /* Set Strobe lines as outputs - set high */ | ||
319 | for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) { | ||
320 | int gpio = TOSA_GPIO_KEY_STROBE(i); | ||
321 | error = gpio_request(gpio, "tosakbd"); | ||
322 | if (error < 0) { | ||
323 | printk(KERN_ERR "tosakbd: failed to request GPIO %d, " | ||
324 | " error %d\n", gpio, error); | ||
325 | goto fail2; | ||
326 | } | ||
327 | |||
328 | error = gpio_direction_output(gpio, 1); | ||
329 | if (error < 0) { | ||
330 | printk(KERN_ERR "tosakbd: failed to configure input" | ||
331 | " direction for GPIO %d, error %d\n", | ||
332 | gpio, error); | ||
333 | gpio_free(gpio); | ||
334 | goto fail; | ||
335 | } | ||
336 | |||
337 | } | ||
338 | |||
339 | error = input_register_device(input_dev); | ||
340 | if (error) { | ||
341 | printk(KERN_ERR "tosakbd: Unable to register input device, " | ||
342 | "error: %d\n", error); | ||
343 | goto fail; | ||
344 | } | ||
345 | |||
346 | printk(KERN_INFO "input: Tosa Keyboard Registered\n"); | ||
347 | |||
348 | return 0; | ||
349 | |||
350 | fail2: | ||
351 | while (--i >= 0) | ||
352 | gpio_free(TOSA_GPIO_KEY_STROBE(i)); | ||
353 | |||
354 | i = TOSA_KEY_SENSE_NUM; | ||
355 | fail: | ||
356 | while (--i >= 0) { | ||
357 | free_irq(gpio_to_irq(TOSA_GPIO_KEY_SENSE(i)), pdev); | ||
358 | gpio_free(TOSA_GPIO_KEY_SENSE(i)); | ||
359 | } | ||
360 | |||
361 | platform_set_drvdata(pdev, NULL); | ||
362 | input_free_device(input_dev); | ||
363 | kfree(tosakbd); | ||
364 | |||
365 | return error; | ||
366 | } | ||
367 | |||
368 | static int __devexit tosakbd_remove(struct platform_device *dev) { | ||
369 | |||
370 | int i; | ||
371 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
372 | |||
373 | for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) | ||
374 | gpio_free(TOSA_GPIO_KEY_STROBE(i)); | ||
375 | |||
376 | for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { | ||
377 | free_irq(gpio_to_irq(TOSA_GPIO_KEY_SENSE(i)), dev); | ||
378 | gpio_free(TOSA_GPIO_KEY_SENSE(i)); | ||
379 | } | ||
380 | |||
381 | del_timer_sync(&tosakbd->timer); | ||
382 | |||
383 | input_unregister_device(tosakbd->input); | ||
384 | |||
385 | kfree(tosakbd); | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | static struct platform_driver tosakbd_driver = { | ||
391 | .probe = tosakbd_probe, | ||
392 | .remove = __devexit_p(tosakbd_remove), | ||
393 | .suspend = tosakbd_suspend, | ||
394 | .resume = tosakbd_resume, | ||
395 | .driver = { | ||
396 | .name = "tosa-keyboard", | ||
397 | }, | ||
398 | }; | ||
399 | |||
400 | static int __devinit tosakbd_init(void) | ||
401 | { | ||
402 | return platform_driver_register(&tosakbd_driver); | ||
403 | } | ||
404 | |||
405 | static void __exit tosakbd_exit(void) | ||
406 | { | ||
407 | platform_driver_unregister(&tosakbd_driver); | ||
408 | } | ||
409 | |||
410 | module_init(tosakbd_init); | ||
411 | module_exit(tosakbd_exit); | ||
412 | |||
413 | MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>"); | ||
414 | MODULE_DESCRIPTION("Tosa Keyboard Driver"); | ||
415 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 8f5c7b90187d..8b10d9f23bef 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -40,6 +40,20 @@ config INPUT_M68K_BEEP | |||
40 | tristate "M68k Beeper support" | 40 | tristate "M68k Beeper support" |
41 | depends on M68K | 41 | depends on M68K |
42 | 42 | ||
43 | config INPUT_APANEL | ||
44 | tristate "Fujitsu Lifebook Application Panel buttons" | ||
45 | depends on X86 | ||
46 | select I2C_I801 | ||
47 | select INPUT_POLLDEV | ||
48 | select CHECK_SIGNATURE | ||
49 | help | ||
50 | Say Y here for support of the Application Panel buttons, used on | ||
51 | Fujitsu Lifebook. These are attached to the mainboard through | ||
52 | an SMBus interface managed by the I2C Intel ICH (i801) driver. | ||
53 | |||
54 | To compile this driver as a module, choose M here: the module will | ||
55 | be called apanel. | ||
56 | |||
43 | config INPUT_IXP4XX_BEEPER | 57 | config INPUT_IXP4XX_BEEPER |
44 | tristate "IXP4XX Beeper support" | 58 | tristate "IXP4XX Beeper support" |
45 | depends on ARCH_IXP4XX | 59 | depends on ARCH_IXP4XX |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 3585b5038418..ebd39f291d25 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -18,3 +18,4 @@ obj-$(CONFIG_INPUT_POWERMATE) += powermate.o | |||
18 | obj-$(CONFIG_INPUT_YEALINK) += yealink.o | 18 | obj-$(CONFIG_INPUT_YEALINK) += yealink.o |
19 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o | 19 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o |
20 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o | 20 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o |
21 | obj-$(CONFIG_INPUT_APANEL) += apanel.o | ||
diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c new file mode 100644 index 000000000000..9531d8c7444f --- /dev/null +++ b/drivers/input/misc/apanel.c | |||
@@ -0,0 +1,378 @@ | |||
1 | /* | ||
2 | * Fujitsu Lifebook Application Panel button drive | ||
3 | * | ||
4 | * Copyright (C) 2007 Stephen Hemminger <shemminger@linux-foundation.org> | ||
5 | * Copyright (C) 2001-2003 Jochen Eisinger <jochen@penguin-breeder.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License version 2 as published by | ||
9 | * the Free Software Foundation. | ||
10 | * | ||
11 | * Many Fujitsu Lifebook laptops have a small panel of buttons that are | ||
12 | * accessible via the i2c/smbus interface. This driver polls those | ||
13 | * buttons and generates input events. | ||
14 | * | ||
15 | * For more details see: | ||
16 | * http://apanel.sourceforge.net/tech.php | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/ioport.h> | ||
22 | #include <linux/io.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/input-polldev.h> | ||
25 | #include <linux/i2c.h> | ||
26 | #include <linux/workqueue.h> | ||
27 | #include <linux/leds.h> | ||
28 | |||
29 | #define APANEL_NAME "Fujitsu Application Panel" | ||
30 | #define APANEL_VERSION "1.3.1" | ||
31 | #define APANEL "apanel" | ||
32 | |||
33 | /* How often we poll keys - msecs */ | ||
34 | #define POLL_INTERVAL_DEFAULT 1000 | ||
35 | |||
36 | /* Magic constants in BIOS that tell about buttons */ | ||
37 | enum apanel_devid { | ||
38 | APANEL_DEV_NONE = 0, | ||
39 | APANEL_DEV_APPBTN = 1, | ||
40 | APANEL_DEV_CDBTN = 2, | ||
41 | APANEL_DEV_LCD = 3, | ||
42 | APANEL_DEV_LED = 4, | ||
43 | |||
44 | APANEL_DEV_MAX, | ||
45 | }; | ||
46 | |||
47 | enum apanel_chip { | ||
48 | CHIP_NONE = 0, | ||
49 | CHIP_OZ992C = 1, | ||
50 | CHIP_OZ163T = 2, | ||
51 | CHIP_OZ711M3 = 4, | ||
52 | }; | ||
53 | |||
54 | /* Result of BIOS snooping/probing -- what features are supported */ | ||
55 | static enum apanel_chip device_chip[APANEL_DEV_MAX]; | ||
56 | |||
57 | #define MAX_PANEL_KEYS 12 | ||
58 | |||
59 | struct apanel { | ||
60 | struct input_polled_dev *ipdev; | ||
61 | struct i2c_client client; | ||
62 | unsigned short keymap[MAX_PANEL_KEYS]; | ||
63 | u16 nkeys; | ||
64 | u16 led_bits; | ||
65 | struct work_struct led_work; | ||
66 | struct led_classdev mail_led; | ||
67 | }; | ||
68 | |||
69 | |||
70 | static int apanel_probe(struct i2c_adapter *, int, int); | ||
71 | |||
72 | /* for now, we only support one address */ | ||
73 | static unsigned short normal_i2c[] = {0, I2C_CLIENT_END}; | ||
74 | static unsigned short ignore = I2C_CLIENT_END; | ||
75 | static struct i2c_client_address_data addr_data = { | ||
76 | .normal_i2c = normal_i2c, | ||
77 | .probe = &ignore, | ||
78 | .ignore = &ignore, | ||
79 | }; | ||
80 | |||
81 | static void report_key(struct input_dev *input, unsigned keycode) | ||
82 | { | ||
83 | pr_debug(APANEL ": report key %#x\n", keycode); | ||
84 | input_report_key(input, keycode, 1); | ||
85 | input_sync(input); | ||
86 | |||
87 | input_report_key(input, keycode, 0); | ||
88 | input_sync(input); | ||
89 | } | ||
90 | |||
91 | /* Poll for key changes | ||
92 | * | ||
93 | * Read Application keys via SMI | ||
94 | * A (0x4), B (0x8), Internet (0x2), Email (0x1). | ||
95 | * | ||
96 | * CD keys: | ||
97 | * Forward (0x100), Rewind (0x200), Stop (0x400), Pause (0x800) | ||
98 | */ | ||
99 | static void apanel_poll(struct input_polled_dev *ipdev) | ||
100 | { | ||
101 | struct apanel *ap = ipdev->private; | ||
102 | struct input_dev *idev = ipdev->input; | ||
103 | u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8; | ||
104 | s32 data; | ||
105 | int i; | ||
106 | |||
107 | data = i2c_smbus_read_word_data(&ap->client, cmd); | ||
108 | if (data < 0) | ||
109 | return; /* ignore errors (due to ACPI??) */ | ||
110 | |||
111 | /* write back to clear latch */ | ||
112 | i2c_smbus_write_word_data(&ap->client, cmd, 0); | ||
113 | |||
114 | if (!data) | ||
115 | return; | ||
116 | |||
117 | dev_dbg(&idev->dev, APANEL ": data %#x\n", data); | ||
118 | for (i = 0; i < idev->keycodemax; i++) | ||
119 | if ((1u << i) & data) | ||
120 | report_key(idev, ap->keymap[i]); | ||
121 | } | ||
122 | |||
123 | /* Track state changes of LED */ | ||
124 | static void led_update(struct work_struct *work) | ||
125 | { | ||
126 | struct apanel *ap = container_of(work, struct apanel, led_work); | ||
127 | |||
128 | i2c_smbus_write_word_data(&ap->client, 0x10, ap->led_bits); | ||
129 | } | ||
130 | |||
131 | static void mail_led_set(struct led_classdev *led, | ||
132 | enum led_brightness value) | ||
133 | { | ||
134 | struct apanel *ap = container_of(led, struct apanel, mail_led); | ||
135 | |||
136 | if (value != LED_OFF) | ||
137 | ap->led_bits |= 0x8000; | ||
138 | else | ||
139 | ap->led_bits &= ~0x8000; | ||
140 | |||
141 | schedule_work(&ap->led_work); | ||
142 | } | ||
143 | |||
144 | static int apanel_detach_client(struct i2c_client *client) | ||
145 | { | ||
146 | struct apanel *ap = i2c_get_clientdata(client); | ||
147 | |||
148 | if (device_chip[APANEL_DEV_LED] != CHIP_NONE) | ||
149 | led_classdev_unregister(&ap->mail_led); | ||
150 | |||
151 | input_unregister_polled_device(ap->ipdev); | ||
152 | i2c_detach_client(&ap->client); | ||
153 | input_free_polled_device(ap->ipdev); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | /* Function is invoked for every i2c adapter. */ | ||
159 | static int apanel_attach_adapter(struct i2c_adapter *adap) | ||
160 | { | ||
161 | dev_dbg(&adap->dev, APANEL ": attach adapter id=%d\n", adap->id); | ||
162 | |||
163 | /* Our device is connected only to i801 on laptop */ | ||
164 | if (adap->id != I2C_HW_SMBUS_I801) | ||
165 | return -ENODEV; | ||
166 | |||
167 | return i2c_probe(adap, &addr_data, apanel_probe); | ||
168 | } | ||
169 | |||
170 | static void apanel_shutdown(struct i2c_client *client) | ||
171 | { | ||
172 | apanel_detach_client(client); | ||
173 | } | ||
174 | |||
175 | static struct i2c_driver apanel_driver = { | ||
176 | .driver = { | ||
177 | .name = APANEL, | ||
178 | }, | ||
179 | .attach_adapter = &apanel_attach_adapter, | ||
180 | .detach_client = &apanel_detach_client, | ||
181 | .shutdown = &apanel_shutdown, | ||
182 | }; | ||
183 | |||
184 | static struct apanel apanel = { | ||
185 | .client = { | ||
186 | .driver = &apanel_driver, | ||
187 | .name = APANEL, | ||
188 | }, | ||
189 | .keymap = { | ||
190 | [0] = KEY_MAIL, | ||
191 | [1] = KEY_WWW, | ||
192 | [2] = KEY_PROG2, | ||
193 | [3] = KEY_PROG1, | ||
194 | |||
195 | [8] = KEY_FORWARD, | ||
196 | [9] = KEY_REWIND, | ||
197 | [10] = KEY_STOPCD, | ||
198 | [11] = KEY_PLAYPAUSE, | ||
199 | |||
200 | }, | ||
201 | .mail_led = { | ||
202 | .name = "mail:blue", | ||
203 | .brightness_set = mail_led_set, | ||
204 | }, | ||
205 | }; | ||
206 | |||
207 | /* NB: Only one panel on the i2c. */ | ||
208 | static int apanel_probe(struct i2c_adapter *bus, int address, int kind) | ||
209 | { | ||
210 | struct apanel *ap; | ||
211 | struct input_polled_dev *ipdev; | ||
212 | struct input_dev *idev; | ||
213 | u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8; | ||
214 | int i, err = -ENOMEM; | ||
215 | |||
216 | dev_dbg(&bus->dev, APANEL ": probe adapter %p addr %d kind %d\n", | ||
217 | bus, address, kind); | ||
218 | |||
219 | ap = &apanel; | ||
220 | |||
221 | ipdev = input_allocate_polled_device(); | ||
222 | if (!ipdev) | ||
223 | goto out1; | ||
224 | |||
225 | ap->ipdev = ipdev; | ||
226 | ap->client.adapter = bus; | ||
227 | ap->client.addr = address; | ||
228 | |||
229 | i2c_set_clientdata(&ap->client, ap); | ||
230 | |||
231 | err = i2c_attach_client(&ap->client); | ||
232 | if (err) | ||
233 | goto out2; | ||
234 | |||
235 | err = i2c_smbus_write_word_data(&ap->client, cmd, 0); | ||
236 | if (err) { | ||
237 | dev_warn(&ap->client.dev, APANEL ": smbus write error %d\n", | ||
238 | err); | ||
239 | goto out3; | ||
240 | } | ||
241 | |||
242 | ipdev->poll = apanel_poll; | ||
243 | ipdev->poll_interval = POLL_INTERVAL_DEFAULT; | ||
244 | ipdev->private = ap; | ||
245 | |||
246 | idev = ipdev->input; | ||
247 | idev->name = APANEL_NAME " buttons"; | ||
248 | idev->phys = "apanel/input0"; | ||
249 | idev->id.bustype = BUS_HOST; | ||
250 | idev->dev.parent = &ap->client.dev; | ||
251 | |||
252 | set_bit(EV_KEY, idev->evbit); | ||
253 | |||
254 | idev->keycode = ap->keymap; | ||
255 | idev->keycodesize = sizeof(ap->keymap[0]); | ||
256 | idev->keycodemax = (device_chip[APANEL_DEV_CDBTN] != CHIP_NONE) ? 12 : 4; | ||
257 | |||
258 | for (i = 0; i < idev->keycodemax; i++) | ||
259 | if (ap->keymap[i]) | ||
260 | set_bit(ap->keymap[i], idev->keybit); | ||
261 | |||
262 | err = input_register_polled_device(ipdev); | ||
263 | if (err) | ||
264 | goto out3; | ||
265 | |||
266 | INIT_WORK(&ap->led_work, led_update); | ||
267 | if (device_chip[APANEL_DEV_LED] != CHIP_NONE) { | ||
268 | err = led_classdev_register(&ap->client.dev, &ap->mail_led); | ||
269 | if (err) | ||
270 | goto out4; | ||
271 | } | ||
272 | |||
273 | return 0; | ||
274 | out4: | ||
275 | input_unregister_polled_device(ipdev); | ||
276 | out3: | ||
277 | i2c_detach_client(&ap->client); | ||
278 | out2: | ||
279 | input_free_polled_device(ipdev); | ||
280 | out1: | ||
281 | return err; | ||
282 | } | ||
283 | |||
284 | /* Scan the system ROM for the signature "FJKEYINF" */ | ||
285 | static __init const void __iomem *bios_signature(const void __iomem *bios) | ||
286 | { | ||
287 | ssize_t offset; | ||
288 | const unsigned char signature[] = "FJKEYINF"; | ||
289 | |||
290 | for (offset = 0; offset < 0x10000; offset += 0x10) { | ||
291 | if (check_signature(bios + offset, signature, | ||
292 | sizeof(signature)-1)) | ||
293 | return bios + offset; | ||
294 | } | ||
295 | pr_notice(APANEL ": Fujitsu BIOS signature '%s' not found...\n", | ||
296 | signature); | ||
297 | return NULL; | ||
298 | } | ||
299 | |||
300 | static int __init apanel_init(void) | ||
301 | { | ||
302 | void __iomem *bios; | ||
303 | const void __iomem *p; | ||
304 | u8 devno; | ||
305 | int found = 0; | ||
306 | |||
307 | bios = ioremap(0xF0000, 0x10000); /* Can't fail */ | ||
308 | |||
309 | p = bios_signature(bios); | ||
310 | if (!p) { | ||
311 | iounmap(bios); | ||
312 | return -ENODEV; | ||
313 | } | ||
314 | |||
315 | /* just use the first address */ | ||
316 | p += 8; | ||
317 | normal_i2c[0] = readb(p+3) >> 1; | ||
318 | |||
319 | for ( ; (devno = readb(p)) & 0x7f; p += 4) { | ||
320 | unsigned char method, slave, chip; | ||
321 | |||
322 | method = readb(p + 1); | ||
323 | chip = readb(p + 2); | ||
324 | slave = readb(p + 3) >> 1; | ||
325 | |||
326 | if (slave != normal_i2c[0]) { | ||
327 | pr_notice(APANEL ": only one SMBus slave " | ||
328 | "address supported, skiping device...\n"); | ||
329 | continue; | ||
330 | } | ||
331 | |||
332 | /* translate alternative device numbers */ | ||
333 | switch (devno) { | ||
334 | case 6: | ||
335 | devno = APANEL_DEV_APPBTN; | ||
336 | break; | ||
337 | case 7: | ||
338 | devno = APANEL_DEV_LED; | ||
339 | break; | ||
340 | } | ||
341 | |||
342 | if (devno >= APANEL_DEV_MAX) | ||
343 | pr_notice(APANEL ": unknown device %u found\n", devno); | ||
344 | else if (device_chip[devno] != CHIP_NONE) | ||
345 | pr_warning(APANEL ": duplicate entry for devno %u\n", devno); | ||
346 | |||
347 | else if (method != 1 && method != 2 && method != 4) { | ||
348 | pr_notice(APANEL ": unknown method %u for devno %u\n", | ||
349 | method, devno); | ||
350 | } else { | ||
351 | device_chip[devno] = (enum apanel_chip) chip; | ||
352 | ++found; | ||
353 | } | ||
354 | } | ||
355 | iounmap(bios); | ||
356 | |||
357 | if (found == 0) { | ||
358 | pr_info(APANEL ": no input devices reported by BIOS\n"); | ||
359 | return -EIO; | ||
360 | } | ||
361 | |||
362 | return i2c_add_driver(&apanel_driver); | ||
363 | } | ||
364 | module_init(apanel_init); | ||
365 | |||
366 | static void __exit apanel_cleanup(void) | ||
367 | { | ||
368 | i2c_del_driver(&apanel_driver); | ||
369 | } | ||
370 | module_exit(apanel_cleanup); | ||
371 | |||
372 | MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>"); | ||
373 | MODULE_DESCRIPTION(APANEL_NAME " driver"); | ||
374 | MODULE_LICENSE("GPL"); | ||
375 | MODULE_VERSION(APANEL_VERSION); | ||
376 | |||
377 | MODULE_ALIAS("dmi:*:svnFUJITSU:pnLifeBook*:pvr*:rvnFUJITSU:*"); | ||
378 | MODULE_ALIAS("dmi:*:svnFUJITSU:pnLifebook*:pvr*:rvnFUJITSU:*"); | ||
diff --git a/drivers/input/misc/ati_remote.c b/drivers/input/misc/ati_remote.c index 3a7937481ad8..f3b86c2b0797 100644 --- a/drivers/input/misc/ati_remote.c +++ b/drivers/input/misc/ati_remote.c | |||
@@ -90,7 +90,6 @@ | |||
90 | #include <linux/init.h> | 90 | #include <linux/init.h> |
91 | #include <linux/slab.h> | 91 | #include <linux/slab.h> |
92 | #include <linux/module.h> | 92 | #include <linux/module.h> |
93 | #include <linux/moduleparam.h> | ||
94 | #include <linux/usb/input.h> | 93 | #include <linux/usb/input.h> |
95 | #include <linux/wait.h> | 94 | #include <linux/wait.h> |
96 | #include <linux/jiffies.h> | 95 | #include <linux/jiffies.h> |
diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c index 4e3ad657ed80..1b871917340a 100644 --- a/drivers/input/misc/atlas_btns.c +++ b/drivers/input/misc/atlas_btns.c | |||
@@ -29,9 +29,10 @@ | |||
29 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
30 | #include <acpi/acpi_drivers.h> | 30 | #include <acpi/acpi_drivers.h> |
31 | 31 | ||
32 | #define ACPI_ATLAS_NAME "Atlas ACPI" | 32 | #define ACPI_ATLAS_NAME "Atlas ACPI" |
33 | #define ACPI_ATLAS_CLASS "Atlas" | 33 | #define ACPI_ATLAS_CLASS "Atlas" |
34 | 34 | ||
35 | static unsigned short atlas_keymap[16]; | ||
35 | static struct input_dev *input_dev; | 36 | static struct input_dev *input_dev; |
36 | 37 | ||
37 | /* button handling code */ | 38 | /* button handling code */ |
@@ -50,12 +51,15 @@ static acpi_status acpi_atlas_button_handler(u32 function, | |||
50 | void *handler_context, void *region_context) | 51 | void *handler_context, void *region_context) |
51 | { | 52 | { |
52 | acpi_status status; | 53 | acpi_status status; |
53 | int keycode; | ||
54 | 54 | ||
55 | if (function == ACPI_WRITE) { | 55 | if (function == ACPI_WRITE) { |
56 | keycode = KEY_F1 + (address & 0x0F); | 56 | int code = address & 0x0f; |
57 | input_report_key(input_dev, keycode, !(address & 0x10)); | 57 | int key_down = !(address & 0x10); |
58 | |||
59 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | ||
60 | input_report_key(input_dev, atlas_keymap[code], key_down); | ||
58 | input_sync(input_dev); | 61 | input_sync(input_dev); |
62 | |||
59 | status = 0; | 63 | status = 0; |
60 | } else { | 64 | } else { |
61 | printk(KERN_WARNING "atlas: shrugged on unexpected function" | 65 | printk(KERN_WARNING "atlas: shrugged on unexpected function" |
@@ -70,6 +74,7 @@ static acpi_status acpi_atlas_button_handler(u32 function, | |||
70 | static int atlas_acpi_button_add(struct acpi_device *device) | 74 | static int atlas_acpi_button_add(struct acpi_device *device) |
71 | { | 75 | { |
72 | acpi_status status; | 76 | acpi_status status; |
77 | int i; | ||
73 | int err; | 78 | int err; |
74 | 79 | ||
75 | input_dev = input_allocate_device(); | 80 | input_dev = input_allocate_device(); |
@@ -81,17 +86,19 @@ static int atlas_acpi_button_add(struct acpi_device *device) | |||
81 | input_dev->name = "Atlas ACPI button driver"; | 86 | input_dev->name = "Atlas ACPI button driver"; |
82 | input_dev->phys = "ASIM0000/atlas/input0"; | 87 | input_dev->phys = "ASIM0000/atlas/input0"; |
83 | input_dev->id.bustype = BUS_HOST; | 88 | input_dev->id.bustype = BUS_HOST; |
84 | input_dev->evbit[BIT_WORD(EV_KEY)] = BIT_MASK(EV_KEY); | 89 | input_dev->keycode = atlas_keymap; |
85 | 90 | input_dev->keycodesize = sizeof(unsigned short); | |
86 | set_bit(KEY_F1, input_dev->keybit); | 91 | input_dev->keycodemax = ARRAY_SIZE(atlas_keymap); |
87 | set_bit(KEY_F2, input_dev->keybit); | 92 | |
88 | set_bit(KEY_F3, input_dev->keybit); | 93 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
89 | set_bit(KEY_F4, input_dev->keybit); | 94 | __set_bit(EV_KEY, input_dev->evbit); |
90 | set_bit(KEY_F5, input_dev->keybit); | 95 | for (i = 0; i < ARRAY_SIZE(atlas_keymap); i++) { |
91 | set_bit(KEY_F6, input_dev->keybit); | 96 | if (i < 9) { |
92 | set_bit(KEY_F7, input_dev->keybit); | 97 | atlas_keymap[i] = KEY_F1 + i; |
93 | set_bit(KEY_F8, input_dev->keybit); | 98 | __set_bit(KEY_F1 + i, input_dev->keybit); |
94 | set_bit(KEY_F9, input_dev->keybit); | 99 | } else |
100 | atlas_keymap[i] = KEY_RESERVED; | ||
101 | } | ||
95 | 102 | ||
96 | err = input_register_device(input_dev); | 103 | err = input_register_device(input_dev); |
97 | if (err) { | 104 | if (err) { |
diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index 1aef97ed5e84..4833b1a82623 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c | |||
@@ -27,55 +27,48 @@ | |||
27 | #define BUTTONS_COUNT_THRESHOLD 3 | 27 | #define BUTTONS_COUNT_THRESHOLD 3 |
28 | #define BUTTONS_STATUS_MASK 0xfe000000 | 28 | #define BUTTONS_STATUS_MASK 0xfe000000 |
29 | 29 | ||
30 | static const unsigned short cobalt_map[] = { | ||
31 | KEY_RESERVED, | ||
32 | KEY_RESTART, | ||
33 | KEY_LEFT, | ||
34 | KEY_UP, | ||
35 | KEY_DOWN, | ||
36 | KEY_RIGHT, | ||
37 | KEY_ENTER, | ||
38 | KEY_SELECT | ||
39 | }; | ||
40 | |||
30 | struct buttons_dev { | 41 | struct buttons_dev { |
31 | struct input_polled_dev *poll_dev; | 42 | struct input_polled_dev *poll_dev; |
43 | unsigned short keymap[ARRAY_SIZE(cobalt_map)]; | ||
44 | int count[ARRAY_SIZE(cobalt_map)]; | ||
32 | void __iomem *reg; | 45 | void __iomem *reg; |
33 | }; | 46 | }; |
34 | 47 | ||
35 | struct buttons_map { | ||
36 | uint32_t mask; | ||
37 | int keycode; | ||
38 | int count; | ||
39 | }; | ||
40 | |||
41 | static struct buttons_map buttons_map[] = { | ||
42 | { 0x02000000, KEY_RESTART, }, | ||
43 | { 0x04000000, KEY_LEFT, }, | ||
44 | { 0x08000000, KEY_UP, }, | ||
45 | { 0x10000000, KEY_DOWN, }, | ||
46 | { 0x20000000, KEY_RIGHT, }, | ||
47 | { 0x40000000, KEY_ENTER, }, | ||
48 | { 0x80000000, KEY_SELECT, }, | ||
49 | }; | ||
50 | |||
51 | static void handle_buttons(struct input_polled_dev *dev) | 48 | static void handle_buttons(struct input_polled_dev *dev) |
52 | { | 49 | { |
53 | struct buttons_map *button = buttons_map; | ||
54 | struct buttons_dev *bdev = dev->private; | 50 | struct buttons_dev *bdev = dev->private; |
55 | struct input_dev *input = dev->input; | 51 | struct input_dev *input = dev->input; |
56 | uint32_t status; | 52 | uint32_t status; |
57 | int i; | 53 | int i; |
58 | 54 | ||
59 | status = readl(bdev->reg); | 55 | status = ~readl(bdev->reg) >> 24; |
60 | status = ~status & BUTTONS_STATUS_MASK; | ||
61 | 56 | ||
62 | for (i = 0; i < ARRAY_SIZE(buttons_map); i++) { | 57 | for (i = 0; i < ARRAY_SIZE(bdev->keymap); i++) { |
63 | if (status & button->mask) { | 58 | if (status & (1UL << i)) { |
64 | button->count++; | 59 | if (++bdev->count[i] == BUTTONS_COUNT_THRESHOLD) { |
60 | input_event(input, EV_MSC, MSC_SCAN, i); | ||
61 | input_report_key(input, bdev->keymap[i], 1); | ||
62 | input_sync(input); | ||
63 | } | ||
65 | } else { | 64 | } else { |
66 | if (button->count >= BUTTONS_COUNT_THRESHOLD) { | 65 | if (bdev->count[i] >= BUTTONS_COUNT_THRESHOLD) { |
67 | input_report_key(input, button->keycode, 0); | 66 | input_event(input, EV_MSC, MSC_SCAN, i); |
67 | input_report_key(input, bdev->keymap[i], 0); | ||
68 | input_sync(input); | 68 | input_sync(input); |
69 | } | 69 | } |
70 | button->count = 0; | 70 | bdev->count[i] = 0; |
71 | } | ||
72 | |||
73 | if (button->count == BUTTONS_COUNT_THRESHOLD) { | ||
74 | input_report_key(input, button->keycode, 1); | ||
75 | input_sync(input); | ||
76 | } | 71 | } |
77 | |||
78 | button++; | ||
79 | } | 72 | } |
80 | } | 73 | } |
81 | 74 | ||
@@ -94,6 +87,8 @@ static int __devinit cobalt_buttons_probe(struct platform_device *pdev) | |||
94 | goto err_free_mem; | 87 | goto err_free_mem; |
95 | } | 88 | } |
96 | 89 | ||
90 | memcpy(bdev->keymap, cobalt_map, sizeof(bdev->keymap)); | ||
91 | |||
97 | poll_dev->private = bdev; | 92 | poll_dev->private = bdev; |
98 | poll_dev->poll = handle_buttons; | 93 | poll_dev->poll = handle_buttons; |
99 | poll_dev->poll_interval = BUTTONS_POLL_INTERVAL; | 94 | poll_dev->poll_interval = BUTTONS_POLL_INTERVAL; |
@@ -104,11 +99,15 @@ static int __devinit cobalt_buttons_probe(struct platform_device *pdev) | |||
104 | input->id.bustype = BUS_HOST; | 99 | input->id.bustype = BUS_HOST; |
105 | input->cdev.dev = &pdev->dev; | 100 | input->cdev.dev = &pdev->dev; |
106 | 101 | ||
107 | input->evbit[0] = BIT_MASK(EV_KEY); | 102 | input->keycode = pdev->keymap; |
108 | for (i = 0; i < ARRAY_SIZE(buttons_map); i++) { | 103 | input->keycodemax = ARRAY_SIZE(pdev->keymap); |
109 | set_bit(buttons_map[i].keycode, input->keybit); | 104 | input->keycodesize = sizeof(unsigned short); |
110 | buttons_map[i].count = 0; | 105 | |
111 | } | 106 | input_set_capability(input, EV_MSC, MSC_SCAN); |
107 | __set_bit(EV_KEY, input->evbit); | ||
108 | for (i = 0; i < ARRAY_SIZE(buttons_map); i++) | ||
109 | __set_bit(input->keycode[i], input->keybit); | ||
110 | __clear_bit(KEY_RESERVED, input->keybit); | ||
112 | 111 | ||
113 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 112 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
114 | if (!res) { | 113 | if (!res) { |
diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c index fd74347047dd..952938a8e991 100644 --- a/drivers/input/misc/keyspan_remote.c +++ b/drivers/input/misc/keyspan_remote.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/usb/input.h> | 19 | #include <linux/usb/input.h> |
21 | 20 | ||
22 | #define DRIVER_VERSION "v0.1" | 21 | #define DRIVER_VERSION "v0.1" |
@@ -46,53 +45,12 @@ MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); | |||
46 | 45 | ||
47 | #define RECV_SIZE 8 /* The UIA-11 type have a 8 byte limit. */ | 46 | #define RECV_SIZE 8 /* The UIA-11 type have a 8 byte limit. */ |
48 | 47 | ||
49 | /* table of devices that work with this driver */ | ||
50 | static struct usb_device_id keyspan_table[] = { | ||
51 | { USB_DEVICE(USB_KEYSPAN_VENDOR_ID, USB_KEYSPAN_PRODUCT_UIA11) }, | ||
52 | { } /* Terminating entry */ | ||
53 | }; | ||
54 | |||
55 | /* Structure to store all the real stuff that a remote sends to us. */ | ||
56 | struct keyspan_message { | ||
57 | u16 system; | ||
58 | u8 button; | ||
59 | u8 toggle; | ||
60 | }; | ||
61 | |||
62 | /* Structure used for all the bit testing magic needed to be done. */ | ||
63 | struct bit_tester { | ||
64 | u32 tester; | ||
65 | int len; | ||
66 | int pos; | ||
67 | int bits_left; | ||
68 | u8 buffer[32]; | ||
69 | }; | ||
70 | |||
71 | /* Structure to hold all of our driver specific stuff */ | ||
72 | struct usb_keyspan { | ||
73 | char name[128]; | ||
74 | char phys[64]; | ||
75 | struct usb_device* udev; | ||
76 | struct input_dev *input; | ||
77 | struct usb_interface* interface; | ||
78 | struct usb_endpoint_descriptor* in_endpoint; | ||
79 | struct urb* irq_urb; | ||
80 | int open; | ||
81 | dma_addr_t in_dma; | ||
82 | unsigned char* in_buffer; | ||
83 | |||
84 | /* variables used to parse messages from remote. */ | ||
85 | struct bit_tester data; | ||
86 | int stage; | ||
87 | int toggle; | ||
88 | }; | ||
89 | |||
90 | /* | 48 | /* |
91 | * Table that maps the 31 possible keycodes to input keys. | 49 | * Table that maps the 31 possible keycodes to input keys. |
92 | * Currently there are 15 and 17 button models so RESERVED codes | 50 | * Currently there are 15 and 17 button models so RESERVED codes |
93 | * are blank areas in the mapping. | 51 | * are blank areas in the mapping. |
94 | */ | 52 | */ |
95 | static const int keyspan_key_table[] = { | 53 | static const unsigned short keyspan_key_table[] = { |
96 | KEY_RESERVED, /* 0 is just a place holder. */ | 54 | KEY_RESERVED, /* 0 is just a place holder. */ |
97 | KEY_RESERVED, | 55 | KEY_RESERVED, |
98 | KEY_STOP, | 56 | KEY_STOP, |
@@ -127,6 +85,48 @@ static const int keyspan_key_table[] = { | |||
127 | KEY_MENU | 85 | KEY_MENU |
128 | }; | 86 | }; |
129 | 87 | ||
88 | /* table of devices that work with this driver */ | ||
89 | static struct usb_device_id keyspan_table[] = { | ||
90 | { USB_DEVICE(USB_KEYSPAN_VENDOR_ID, USB_KEYSPAN_PRODUCT_UIA11) }, | ||
91 | { } /* Terminating entry */ | ||
92 | }; | ||
93 | |||
94 | /* Structure to store all the real stuff that a remote sends to us. */ | ||
95 | struct keyspan_message { | ||
96 | u16 system; | ||
97 | u8 button; | ||
98 | u8 toggle; | ||
99 | }; | ||
100 | |||
101 | /* Structure used for all the bit testing magic needed to be done. */ | ||
102 | struct bit_tester { | ||
103 | u32 tester; | ||
104 | int len; | ||
105 | int pos; | ||
106 | int bits_left; | ||
107 | u8 buffer[32]; | ||
108 | }; | ||
109 | |||
110 | /* Structure to hold all of our driver specific stuff */ | ||
111 | struct usb_keyspan { | ||
112 | char name[128]; | ||
113 | char phys[64]; | ||
114 | unsigned short keymap[ARRAY_SIZE(keyspan_key_table)]; | ||
115 | struct usb_device *udev; | ||
116 | struct input_dev *input; | ||
117 | struct usb_interface *interface; | ||
118 | struct usb_endpoint_descriptor *in_endpoint; | ||
119 | struct urb* irq_urb; | ||
120 | int open; | ||
121 | dma_addr_t in_dma; | ||
122 | unsigned char *in_buffer; | ||
123 | |||
124 | /* variables used to parse messages from remote. */ | ||
125 | struct bit_tester data; | ||
126 | int stage; | ||
127 | int toggle; | ||
128 | }; | ||
129 | |||
130 | static struct usb_driver keyspan_driver; | 130 | static struct usb_driver keyspan_driver; |
131 | 131 | ||
132 | /* | 132 | /* |
@@ -173,6 +173,15 @@ static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed) | |||
173 | return 0; | 173 | return 0; |
174 | } | 174 | } |
175 | 175 | ||
176 | static void keyspan_report_button(struct usb_keyspan *remote, int button, int press) | ||
177 | { | ||
178 | struct input_dev *input = remote->input; | ||
179 | |||
180 | input_event(input, EV_MSC, MSC_SCAN, button); | ||
181 | input_report_key(input, remote->keymap[button], press); | ||
182 | input_sync(input); | ||
183 | } | ||
184 | |||
176 | /* | 185 | /* |
177 | * Routine that handles all the logic needed to parse out the message from the remote. | 186 | * Routine that handles all the logic needed to parse out the message from the remote. |
178 | */ | 187 | */ |
@@ -311,9 +320,8 @@ static void keyspan_check_data(struct usb_keyspan *remote) | |||
311 | __FUNCTION__, message.system, message.button, message.toggle); | 320 | __FUNCTION__, message.system, message.button, message.toggle); |
312 | 321 | ||
313 | if (message.toggle != remote->toggle) { | 322 | if (message.toggle != remote->toggle) { |
314 | input_report_key(remote->input, keyspan_key_table[message.button], 1); | 323 | keyspan_report_button(remote, message.button, 1); |
315 | input_report_key(remote->input, keyspan_key_table[message.button], 0); | 324 | keyspan_report_button(remote, message.button, 0); |
316 | input_sync(remote->input); | ||
317 | remote->toggle = message.toggle; | 325 | remote->toggle = message.toggle; |
318 | } | 326 | } |
319 | 327 | ||
@@ -491,16 +499,21 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic | |||
491 | 499 | ||
492 | usb_make_path(udev, remote->phys, sizeof(remote->phys)); | 500 | usb_make_path(udev, remote->phys, sizeof(remote->phys)); |
493 | strlcat(remote->phys, "/input0", sizeof(remote->phys)); | 501 | strlcat(remote->phys, "/input0", sizeof(remote->phys)); |
502 | memcpy(remote->keymap, keyspan_key_table, sizeof(remote->keymap)); | ||
494 | 503 | ||
495 | input_dev->name = remote->name; | 504 | input_dev->name = remote->name; |
496 | input_dev->phys = remote->phys; | 505 | input_dev->phys = remote->phys; |
497 | usb_to_input_id(udev, &input_dev->id); | 506 | usb_to_input_id(udev, &input_dev->id); |
498 | input_dev->dev.parent = &interface->dev; | 507 | input_dev->dev.parent = &interface->dev; |
508 | input_dev->keycode = remote->keymap; | ||
509 | input_dev->keycodesize = sizeof(unsigned short); | ||
510 | input_dev->keycodemax = ARRAY_SIZE(remote->keymap); | ||
499 | 511 | ||
500 | input_dev->evbit[0] = BIT_MASK(EV_KEY); /* We will only report KEY events. */ | 512 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
513 | __set_bit(EV_KEY, input_dev->evbit); | ||
501 | for (i = 0; i < ARRAY_SIZE(keyspan_key_table); i++) | 514 | for (i = 0; i < ARRAY_SIZE(keyspan_key_table); i++) |
502 | if (keyspan_key_table[i] != KEY_RESERVED) | 515 | __set_bit(keyspan_key_table[i], input_dev->keybit); |
503 | set_bit(keyspan_key_table[i], input_dev->keybit); | 516 | __clear_bit(KEY_RESERVED, input_dev->keybit); |
504 | 517 | ||
505 | input_set_drvdata(input_dev, remote); | 518 | input_set_drvdata(input_dev, remote); |
506 | 519 | ||
@@ -508,12 +521,14 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic | |||
508 | input_dev->close = keyspan_close; | 521 | input_dev->close = keyspan_close; |
509 | 522 | ||
510 | /* | 523 | /* |
511 | * Initialize the URB to access the device. The urb gets sent to the device in keyspan_open() | 524 | * Initialize the URB to access the device. |
525 | * The urb gets sent to the device in keyspan_open() | ||
512 | */ | 526 | */ |
513 | usb_fill_int_urb(remote->irq_urb, | 527 | usb_fill_int_urb(remote->irq_urb, |
514 | remote->udev, usb_rcvintpipe(remote->udev, remote->in_endpoint->bEndpointAddress), | 528 | remote->udev, |
529 | usb_rcvintpipe(remote->udev, endpoint->bEndpointAddress), | ||
515 | remote->in_buffer, RECV_SIZE, keyspan_irq_recv, remote, | 530 | remote->in_buffer, RECV_SIZE, keyspan_irq_recv, remote, |
516 | remote->in_endpoint->bInterval); | 531 | endpoint->bInterval); |
517 | remote->irq_urb->transfer_dma = remote->in_dma; | 532 | remote->irq_urb->transfer_dma = remote->in_dma; |
518 | remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 533 | remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
519 | 534 | ||
diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c index 26ec09529b51..06c35fc553c0 100644 --- a/drivers/input/mouse/inport.c +++ b/drivers/input/mouse/inport.c | |||
@@ -35,7 +35,6 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
38 | #include <linux/moduleparam.h> | ||
39 | #include <linux/ioport.h> | 38 | #include <linux/ioport.h> |
40 | #include <linux/init.h> | 39 | #include <linux/init.h> |
41 | #include <linux/interrupt.h> | 40 | #include <linux/interrupt.h> |
diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c index 37e7c75b43bd..9ea895593b27 100644 --- a/drivers/input/mouse/logibm.c +++ b/drivers/input/mouse/logibm.c | |||
@@ -36,7 +36,6 @@ | |||
36 | */ | 36 | */ |
37 | 37 | ||
38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
39 | #include <linux/moduleparam.h> | ||
40 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
41 | #include <linux/ioport.h> | 40 | #include <linux/ioport.h> |
42 | #include <linux/init.h> | 41 | #include <linux/init.h> |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index b8628252e10c..f5a6be1d3c46 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
18 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
19 | #include <linux/input.h> | 18 | #include <linux/input.h> |
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index 9ab5b5ea809d..26b845fc186a 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
12 | #include <linux/serio.h> | 12 | #include <linux/serio.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/input.h> | 14 | #include <linux/input.h> |
16 | #include <linux/libps2.h> | 15 | #include <linux/libps2.h> |
17 | #include <linux/proc_fs.h> | 16 | #include <linux/proc_fs.h> |
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index be83516c776c..bbbe5e81adc1 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/poll.h> | 17 | #include <linux/poll.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/init.h> | 19 | #include <linux/init.h> |
21 | #include <linux/input.h> | 20 | #include <linux/input.h> |
22 | #include <linux/random.h> | 21 | #include <linux/random.h> |
@@ -1033,7 +1032,7 @@ static const struct input_device_id mousedev_ids[] = { | |||
1033 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | | 1032 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
1034 | INPUT_DEVICE_ID_MATCH_KEYBIT | | 1033 | INPUT_DEVICE_ID_MATCH_KEYBIT | |
1035 | INPUT_DEVICE_ID_MATCH_ABSBIT, | 1034 | INPUT_DEVICE_ID_MATCH_ABSBIT, |
1036 | .evbit = { BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_SYN) }, | 1035 | .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) }, |
1037 | .keybit = { [BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) }, | 1036 | .keybit = { [BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) }, |
1038 | .absbit = { BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) }, | 1037 | .absbit = { BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) }, |
1039 | }, /* Mouse-like device with absolute X and Y but ordinary | 1038 | }, /* Mouse-like device with absolute X and Y but ordinary |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index c5e68dcd88ac..662e84482c26 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -63,7 +63,7 @@ static inline void i8042_write_command(int val) | |||
63 | outb(val, I8042_COMMAND_REG); | 63 | outb(val, I8042_COMMAND_REG); |
64 | } | 64 | } |
65 | 65 | ||
66 | #if defined(__i386__) | 66 | #if defined(__i386__) || defined(__x86_64__) |
67 | 67 | ||
68 | #include <linux/dmi.h> | 68 | #include <linux/dmi.h> |
69 | 69 | ||
@@ -186,6 +186,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
186 | }, | 186 | }, |
187 | }, | 187 | }, |
188 | { | 188 | { |
189 | .ident = "Fujitsu-Siemens Amilo Pro 2010", | ||
190 | .matches = { | ||
191 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
192 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2010"), | ||
193 | }, | ||
194 | }, | ||
195 | { | ||
189 | /* | 196 | /* |
190 | * No data is coming from the touchscreen unless KBC | 197 | * No data is coming from the touchscreen unless KBC |
191 | * is in legacy mode. | 198 | * is in legacy mode. |
@@ -277,6 +284,57 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
277 | 284 | ||
278 | #endif | 285 | #endif |
279 | 286 | ||
287 | #ifdef CONFIG_X86 | ||
288 | |||
289 | #include <linux/dmi.h> | ||
290 | |||
291 | /* | ||
292 | * Some Wistron based laptops need us to explicitly enable the 'Dritek | ||
293 | * keyboard extension' to make their extra keys start generating scancodes. | ||
294 | * Originally, this was just confined to older laptops, but a few Acer laptops | ||
295 | * have turned up in 2007 that also need this again. | ||
296 | */ | ||
297 | static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = { | ||
298 | { | ||
299 | .ident = "Acer Aspire 5630", | ||
300 | .matches = { | ||
301 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
302 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"), | ||
303 | }, | ||
304 | }, | ||
305 | { | ||
306 | .ident = "Acer Aspire 5650", | ||
307 | .matches = { | ||
308 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
309 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"), | ||
310 | }, | ||
311 | }, | ||
312 | { | ||
313 | .ident = "Acer Aspire 5680", | ||
314 | .matches = { | ||
315 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
316 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"), | ||
317 | }, | ||
318 | }, | ||
319 | { | ||
320 | .ident = "Acer Aspire 9110", | ||
321 | .matches = { | ||
322 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
323 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"), | ||
324 | }, | ||
325 | }, | ||
326 | { | ||
327 | .ident = "Acer TravelMate 2490", | ||
328 | .matches = { | ||
329 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
330 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"), | ||
331 | }, | ||
332 | }, | ||
333 | { } | ||
334 | }; | ||
335 | |||
336 | #endif /* CONFIG_X86 */ | ||
337 | |||
280 | 338 | ||
281 | #ifdef CONFIG_PNP | 339 | #ifdef CONFIG_PNP |
282 | #include <linux/pnp.h> | 340 | #include <linux/pnp.h> |
@@ -512,7 +570,7 @@ static int __init i8042_platform_init(void) | |||
512 | i8042_reset = 1; | 570 | i8042_reset = 1; |
513 | #endif | 571 | #endif |
514 | 572 | ||
515 | #if defined(__i386__) | 573 | #if defined(__i386__) || defined(__x86_64__) |
516 | if (dmi_check_system(i8042_dmi_noloop_table)) | 574 | if (dmi_check_system(i8042_dmi_noloop_table)) |
517 | i8042_noloop = 1; | 575 | i8042_noloop = 1; |
518 | 576 | ||
@@ -520,6 +578,11 @@ static int __init i8042_platform_init(void) | |||
520 | i8042_nomux = 1; | 578 | i8042_nomux = 1; |
521 | #endif | 579 | #endif |
522 | 580 | ||
581 | #ifdef CONFIG_X86 | ||
582 | if (dmi_check_system(i8042_dmi_dritek_table)) | ||
583 | i8042_dritek = 1; | ||
584 | #endif /* CONFIG_X86 */ | ||
585 | |||
523 | return retval; | 586 | return retval; |
524 | } | 587 | } |
525 | 588 | ||
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 1a0cea3c5294..2763394869d2 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -12,7 +12,6 @@ | |||
12 | 12 | ||
13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
17 | #include <linux/ioport.h> | 16 | #include <linux/ioport.h> |
18 | #include <linux/init.h> | 17 | #include <linux/init.h> |
@@ -64,6 +63,12 @@ static unsigned int i8042_blink_frequency = 500; | |||
64 | module_param_named(panicblink, i8042_blink_frequency, uint, 0600); | 63 | module_param_named(panicblink, i8042_blink_frequency, uint, 0600); |
65 | MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics"); | 64 | MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics"); |
66 | 65 | ||
66 | #ifdef CONFIG_X86 | ||
67 | static unsigned int i8042_dritek; | ||
68 | module_param_named(dritek, i8042_dritek, bool, 0); | ||
69 | MODULE_PARM_DESC(dritek, "Force enable the Dritek keyboard extension"); | ||
70 | #endif | ||
71 | |||
67 | #ifdef CONFIG_PNP | 72 | #ifdef CONFIG_PNP |
68 | static int i8042_nopnp; | 73 | static int i8042_nopnp; |
69 | module_param_named(nopnp, i8042_nopnp, bool, 0); | 74 | module_param_named(nopnp, i8042_nopnp, bool, 0); |
@@ -280,7 +285,14 @@ static void i8042_stop(struct serio *serio) | |||
280 | struct i8042_port *port = serio->port_data; | 285 | struct i8042_port *port = serio->port_data; |
281 | 286 | ||
282 | port->exists = 0; | 287 | port->exists = 0; |
283 | synchronize_sched(); | 288 | |
289 | /* | ||
290 | * We synchronize with both AUX and KBD IRQs because there is | ||
291 | * a (very unlikely) chance that AUX IRQ is raised for KBD port | ||
292 | * and vice versa. | ||
293 | */ | ||
294 | synchronize_irq(I8042_AUX_IRQ); | ||
295 | synchronize_irq(I8042_KBD_IRQ); | ||
284 | port->serio = NULL; | 296 | port->serio = NULL; |
285 | } | 297 | } |
286 | 298 | ||
@@ -1139,6 +1151,7 @@ static int __devinit i8042_setup_kbd(void) | |||
1139 | static int __devinit i8042_probe(struct platform_device *dev) | 1151 | static int __devinit i8042_probe(struct platform_device *dev) |
1140 | { | 1152 | { |
1141 | int error; | 1153 | int error; |
1154 | char param; | ||
1142 | 1155 | ||
1143 | error = i8042_controller_selftest(); | 1156 | error = i8042_controller_selftest(); |
1144 | if (error) | 1157 | if (error) |
@@ -1159,7 +1172,14 @@ static int __devinit i8042_probe(struct platform_device *dev) | |||
1159 | if (error) | 1172 | if (error) |
1160 | goto out_fail; | 1173 | goto out_fail; |
1161 | } | 1174 | } |
1162 | 1175 | #ifdef CONFIG_X86 | |
1176 | if (i8042_dritek) { | ||
1177 | param = 0x90; | ||
1178 | error = i8042_command(¶m, 0x1059); | ||
1179 | if (error) | ||
1180 | goto out_fail; | ||
1181 | } | ||
1182 | #endif | ||
1163 | /* | 1183 | /* |
1164 | * Ok, everything is ready, let's register all serio ports | 1184 | * Ok, everything is ready, let's register all serio ports |
1165 | */ | 1185 | */ |
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 10d9d74ae43a..b819239d74dc 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
18 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
19 | #include <linux/input.h> | 18 | #include <linux/input.h> |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index fd9c5d51870a..58934a40f5ce 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -116,6 +116,7 @@ struct ads7846 { | |||
116 | // FIXME remove "irq_disabled" | 116 | // FIXME remove "irq_disabled" |
117 | unsigned irq_disabled:1; /* P: lock */ | 117 | unsigned irq_disabled:1; /* P: lock */ |
118 | unsigned disabled:1; | 118 | unsigned disabled:1; |
119 | unsigned is_suspended:1; | ||
119 | 120 | ||
120 | int (*filter)(void *data, int data_idx, int *val); | 121 | int (*filter)(void *data, int data_idx, int *val); |
121 | void *filter_data; | 122 | void *filter_data; |
@@ -203,7 +204,7 @@ static void ads7846_disable(struct ads7846 *ts); | |||
203 | static int device_suspended(struct device *dev) | 204 | static int device_suspended(struct device *dev) |
204 | { | 205 | { |
205 | struct ads7846 *ts = dev_get_drvdata(dev); | 206 | struct ads7846 *ts = dev_get_drvdata(dev); |
206 | return dev->power.power_state.event != PM_EVENT_ON || ts->disabled; | 207 | return ts->is_suspended || ts->disabled; |
207 | } | 208 | } |
208 | 209 | ||
209 | static int ads7846_read12_ser(struct device *dev, unsigned command) | 210 | static int ads7846_read12_ser(struct device *dev, unsigned command) |
@@ -794,7 +795,7 @@ static int ads7846_suspend(struct spi_device *spi, pm_message_t message) | |||
794 | 795 | ||
795 | spin_lock_irq(&ts->lock); | 796 | spin_lock_irq(&ts->lock); |
796 | 797 | ||
797 | spi->dev.power.power_state = message; | 798 | ts->is_suspended = 1; |
798 | ads7846_disable(ts); | 799 | ads7846_disable(ts); |
799 | 800 | ||
800 | spin_unlock_irq(&ts->lock); | 801 | spin_unlock_irq(&ts->lock); |
@@ -809,7 +810,7 @@ static int ads7846_resume(struct spi_device *spi) | |||
809 | 810 | ||
810 | spin_lock_irq(&ts->lock); | 811 | spin_lock_irq(&ts->lock); |
811 | 812 | ||
812 | spi->dev.power.power_state = PMSG_ON; | 813 | ts->is_suspended = 0; |
813 | ads7846_enable(ts); | 814 | ads7846_enable(ts); |
814 | 815 | ||
815 | spin_unlock_irq(&ts->lock); | 816 | spin_unlock_irq(&ts->lock); |
@@ -871,7 +872,6 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
871 | } | 872 | } |
872 | 873 | ||
873 | dev_set_drvdata(&spi->dev, ts); | 874 | dev_set_drvdata(&spi->dev, ts); |
874 | spi->dev.power.power_state = PMSG_ON; | ||
875 | 875 | ||
876 | ts->spi = spi; | 876 | ts->spi = spi; |
877 | ts->input = input_dev; | 877 | ts->input = input_dev; |
diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c index 80a658868706..efd3aebaba5f 100644 --- a/drivers/input/touchscreen/mk712.c +++ b/drivers/input/touchscreen/mk712.c | |||
@@ -36,7 +36,6 @@ | |||
36 | */ | 36 | */ |
37 | 37 | ||
38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
39 | #include <linux/moduleparam.h> | ||
40 | #include <linux/kernel.h> | 39 | #include <linux/kernel.h> |
41 | #include <linux/init.h> | 40 | #include <linux/init.h> |
42 | #include <linux/errno.h> | 41 | #include <linux/errno.h> |
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 986a8365e37f..607f9933aa1f 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c | |||
@@ -15,7 +15,6 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/moduleparam.h> | ||
19 | #include <linux/init.h> | 18 | #include <linux/init.h> |
20 | #include <linux/completion.h> | 19 | #include <linux/completion.h> |
21 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c index 3e93f8058770..719b17ce83f8 100644 --- a/drivers/media/video/usbvideo/konicawc.c +++ b/drivers/media/video/usbvideo/konicawc.c | |||
@@ -241,8 +241,6 @@ static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev | |||
241 | input_dev->evbit[0] = BIT_MASK(EV_KEY); | 241 | input_dev->evbit[0] = BIT_MASK(EV_KEY); |
242 | input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); | 242 | input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); |
243 | 243 | ||
244 | input_dev->private = cam; | ||
245 | |||
246 | error = input_register_device(cam->input); | 244 | error = input_register_device(cam->input); |
247 | if (error) { | 245 | if (error) { |
248 | warn("Failed to register camera's input device, err: %d\n", | 246 | warn("Failed to register camera's input device, err: %d\n", |
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index 5e7b79501370..a2acba0bcc47 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c | |||
@@ -105,8 +105,6 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev) | |||
105 | input_dev->evbit[0] = BIT_MASK(EV_KEY); | 105 | input_dev->evbit[0] = BIT_MASK(EV_KEY); |
106 | input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); | 106 | input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); |
107 | 107 | ||
108 | input_dev->private = cam; | ||
109 | |||
110 | error = input_register_device(cam->input); | 108 | error = input_register_device(cam->input); |
111 | if (error) { | 109 | if (error) { |
112 | warn("Failed to register camera's input device, err: %d\n", | 110 | warn("Failed to register camera's input device, err: %d\n", |
diff --git a/fs/ocfs2/cluster/tcp_internal.h b/fs/ocfs2/cluster/tcp_internal.h index b2e832aca567..d25b9af28500 100644 --- a/fs/ocfs2/cluster/tcp_internal.h +++ b/fs/ocfs2/cluster/tcp_internal.h | |||
@@ -38,6 +38,15 @@ | |||
38 | * locking semantics of the file system using the protocol. It should | 38 | * locking semantics of the file system using the protocol. It should |
39 | * be somewhere else, I'm sure, but right now it isn't. | 39 | * be somewhere else, I'm sure, but right now it isn't. |
40 | * | 40 | * |
41 | * With version 11, we separate out the filesystem locking portion. The | ||
42 | * filesystem now has a major.minor version it negotiates. Version 11 | ||
43 | * introduces this negotiation to the o2dlm protocol, and as such the | ||
44 | * version here in tcp_internal.h should not need to be bumped for | ||
45 | * filesystem locking changes. | ||
46 | * | ||
47 | * New in version 11 | ||
48 | * - Negotiation of filesystem locking in the dlm join. | ||
49 | * | ||
41 | * New in version 10: | 50 | * New in version 10: |
42 | * - Meta/data locks combined | 51 | * - Meta/data locks combined |
43 | * | 52 | * |
@@ -66,7 +75,7 @@ | |||
66 | * - full 64 bit i_size in the metadata lock lvbs | 75 | * - full 64 bit i_size in the metadata lock lvbs |
67 | * - introduction of "rw" lock and pushing meta/data locking down | 76 | * - introduction of "rw" lock and pushing meta/data locking down |
68 | */ | 77 | */ |
69 | #define O2NET_PROTOCOL_VERSION 10ULL | 78 | #define O2NET_PROTOCOL_VERSION 11ULL |
70 | struct o2net_handshake { | 79 | struct o2net_handshake { |
71 | __be64 protocol_version; | 80 | __be64 protocol_version; |
72 | __be64 connector_id; | 81 | __be64 connector_id; |
diff --git a/fs/ocfs2/dlm/dlmapi.h b/fs/ocfs2/dlm/dlmapi.h index cfd5cb65cab0..b5786a787fab 100644 --- a/fs/ocfs2/dlm/dlmapi.h +++ b/fs/ocfs2/dlm/dlmapi.h | |||
@@ -193,7 +193,12 @@ enum dlm_status dlmunlock(struct dlm_ctxt *dlm, | |||
193 | dlm_astunlockfunc_t *unlockast, | 193 | dlm_astunlockfunc_t *unlockast, |
194 | void *data); | 194 | void *data); |
195 | 195 | ||
196 | struct dlm_ctxt * dlm_register_domain(const char *domain, u32 key); | 196 | struct dlm_protocol_version { |
197 | u8 pv_major; | ||
198 | u8 pv_minor; | ||
199 | }; | ||
200 | struct dlm_ctxt * dlm_register_domain(const char *domain, u32 key, | ||
201 | struct dlm_protocol_version *fs_proto); | ||
197 | 202 | ||
198 | void dlm_unregister_domain(struct dlm_ctxt *dlm); | 203 | void dlm_unregister_domain(struct dlm_ctxt *dlm); |
199 | 204 | ||
diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h index e90b92f9ece1..9843ee17ea27 100644 --- a/fs/ocfs2/dlm/dlmcommon.h +++ b/fs/ocfs2/dlm/dlmcommon.h | |||
@@ -142,6 +142,12 @@ struct dlm_ctxt | |||
142 | spinlock_t work_lock; | 142 | spinlock_t work_lock; |
143 | struct list_head dlm_domain_handlers; | 143 | struct list_head dlm_domain_handlers; |
144 | struct list_head dlm_eviction_callbacks; | 144 | struct list_head dlm_eviction_callbacks; |
145 | |||
146 | /* The filesystem specifies this at domain registration. We | ||
147 | * cache it here to know what to tell other nodes. */ | ||
148 | struct dlm_protocol_version fs_locking_proto; | ||
149 | /* This is the inter-dlm communication version */ | ||
150 | struct dlm_protocol_version dlm_locking_proto; | ||
145 | }; | 151 | }; |
146 | 152 | ||
147 | static inline struct hlist_head *dlm_lockres_hash(struct dlm_ctxt *dlm, unsigned i) | 153 | static inline struct hlist_head *dlm_lockres_hash(struct dlm_ctxt *dlm, unsigned i) |
@@ -589,10 +595,24 @@ struct dlm_proxy_ast | |||
589 | #define DLM_PROXY_AST_MAX_LEN (sizeof(struct dlm_proxy_ast)+DLM_LVB_LEN) | 595 | #define DLM_PROXY_AST_MAX_LEN (sizeof(struct dlm_proxy_ast)+DLM_LVB_LEN) |
590 | 596 | ||
591 | #define DLM_MOD_KEY (0x666c6172) | 597 | #define DLM_MOD_KEY (0x666c6172) |
592 | enum dlm_query_join_response { | 598 | enum dlm_query_join_response_code { |
593 | JOIN_DISALLOW = 0, | 599 | JOIN_DISALLOW = 0, |
594 | JOIN_OK, | 600 | JOIN_OK, |
595 | JOIN_OK_NO_MAP, | 601 | JOIN_OK_NO_MAP, |
602 | JOIN_PROTOCOL_MISMATCH, | ||
603 | }; | ||
604 | |||
605 | union dlm_query_join_response { | ||
606 | u32 intval; | ||
607 | struct { | ||
608 | u8 code; /* Response code. dlm_minor and fs_minor | ||
609 | are only valid if this is JOIN_OK */ | ||
610 | u8 dlm_minor; /* The minor version of the protocol the | ||
611 | dlm is speaking. */ | ||
612 | u8 fs_minor; /* The minor version of the protocol the | ||
613 | filesystem is speaking. */ | ||
614 | u8 reserved; | ||
615 | } packet; | ||
596 | }; | 616 | }; |
597 | 617 | ||
598 | struct dlm_lock_request | 618 | struct dlm_lock_request |
@@ -633,6 +653,8 @@ struct dlm_query_join_request | |||
633 | u8 node_idx; | 653 | u8 node_idx; |
634 | u8 pad1[2]; | 654 | u8 pad1[2]; |
635 | u8 name_len; | 655 | u8 name_len; |
656 | struct dlm_protocol_version dlm_proto; | ||
657 | struct dlm_protocol_version fs_proto; | ||
636 | u8 domain[O2NM_MAX_NAME_LEN]; | 658 | u8 domain[O2NM_MAX_NAME_LEN]; |
637 | u8 node_map[BITS_TO_BYTES(O2NM_MAX_NODES)]; | 659 | u8 node_map[BITS_TO_BYTES(O2NM_MAX_NODES)]; |
638 | }; | 660 | }; |
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 6954565b8ccb..638d2ebb892b 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c | |||
@@ -123,6 +123,17 @@ DEFINE_SPINLOCK(dlm_domain_lock); | |||
123 | LIST_HEAD(dlm_domains); | 123 | LIST_HEAD(dlm_domains); |
124 | static DECLARE_WAIT_QUEUE_HEAD(dlm_domain_events); | 124 | static DECLARE_WAIT_QUEUE_HEAD(dlm_domain_events); |
125 | 125 | ||
126 | /* | ||
127 | * The supported protocol version for DLM communication. Running domains | ||
128 | * will have a negotiated version with the same major number and a minor | ||
129 | * number equal or smaller. The dlm_ctxt->dlm_locking_proto field should | ||
130 | * be used to determine what a running domain is actually using. | ||
131 | */ | ||
132 | static const struct dlm_protocol_version dlm_protocol = { | ||
133 | .pv_major = 1, | ||
134 | .pv_minor = 0, | ||
135 | }; | ||
136 | |||
126 | #define DLM_DOMAIN_BACKOFF_MS 200 | 137 | #define DLM_DOMAIN_BACKOFF_MS 200 |
127 | 138 | ||
128 | static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, | 139 | static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, |
@@ -133,6 +144,8 @@ static int dlm_cancel_join_handler(struct o2net_msg *msg, u32 len, void *data, | |||
133 | void **ret_data); | 144 | void **ret_data); |
134 | static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data, | 145 | static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data, |
135 | void **ret_data); | 146 | void **ret_data); |
147 | static int dlm_protocol_compare(struct dlm_protocol_version *existing, | ||
148 | struct dlm_protocol_version *request); | ||
136 | 149 | ||
137 | static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm); | 150 | static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm); |
138 | 151 | ||
@@ -668,11 +681,45 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm) | |||
668 | } | 681 | } |
669 | EXPORT_SYMBOL_GPL(dlm_unregister_domain); | 682 | EXPORT_SYMBOL_GPL(dlm_unregister_domain); |
670 | 683 | ||
684 | static int dlm_query_join_proto_check(char *proto_type, int node, | ||
685 | struct dlm_protocol_version *ours, | ||
686 | struct dlm_protocol_version *request) | ||
687 | { | ||
688 | int rc; | ||
689 | struct dlm_protocol_version proto = *request; | ||
690 | |||
691 | if (!dlm_protocol_compare(ours, &proto)) { | ||
692 | mlog(0, | ||
693 | "node %u wanted to join with %s locking protocol " | ||
694 | "%u.%u, we respond with %u.%u\n", | ||
695 | node, proto_type, | ||
696 | request->pv_major, | ||
697 | request->pv_minor, | ||
698 | proto.pv_major, proto.pv_minor); | ||
699 | request->pv_minor = proto.pv_minor; | ||
700 | rc = 0; | ||
701 | } else { | ||
702 | mlog(ML_NOTICE, | ||
703 | "Node %u wanted to join with %s locking " | ||
704 | "protocol %u.%u, but we have %u.%u, disallowing\n", | ||
705 | node, proto_type, | ||
706 | request->pv_major, | ||
707 | request->pv_minor, | ||
708 | ours->pv_major, | ||
709 | ours->pv_minor); | ||
710 | rc = 1; | ||
711 | } | ||
712 | |||
713 | return rc; | ||
714 | } | ||
715 | |||
671 | static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, | 716 | static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, |
672 | void **ret_data) | 717 | void **ret_data) |
673 | { | 718 | { |
674 | struct dlm_query_join_request *query; | 719 | struct dlm_query_join_request *query; |
675 | enum dlm_query_join_response response; | 720 | union dlm_query_join_response response = { |
721 | .packet.code = JOIN_DISALLOW, | ||
722 | }; | ||
676 | struct dlm_ctxt *dlm = NULL; | 723 | struct dlm_ctxt *dlm = NULL; |
677 | u8 nodenum; | 724 | u8 nodenum; |
678 | 725 | ||
@@ -690,11 +737,11 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, | |||
690 | mlog(0, "node %u is not in our live map yet\n", | 737 | mlog(0, "node %u is not in our live map yet\n", |
691 | query->node_idx); | 738 | query->node_idx); |
692 | 739 | ||
693 | response = JOIN_DISALLOW; | 740 | response.packet.code = JOIN_DISALLOW; |
694 | goto respond; | 741 | goto respond; |
695 | } | 742 | } |
696 | 743 | ||
697 | response = JOIN_OK_NO_MAP; | 744 | response.packet.code = JOIN_OK_NO_MAP; |
698 | 745 | ||
699 | spin_lock(&dlm_domain_lock); | 746 | spin_lock(&dlm_domain_lock); |
700 | dlm = __dlm_lookup_domain_full(query->domain, query->name_len); | 747 | dlm = __dlm_lookup_domain_full(query->domain, query->name_len); |
@@ -713,7 +760,7 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, | |||
713 | mlog(0, "disallow join as node %u does not " | 760 | mlog(0, "disallow join as node %u does not " |
714 | "have node %u in its nodemap\n", | 761 | "have node %u in its nodemap\n", |
715 | query->node_idx, nodenum); | 762 | query->node_idx, nodenum); |
716 | response = JOIN_DISALLOW; | 763 | response.packet.code = JOIN_DISALLOW; |
717 | goto unlock_respond; | 764 | goto unlock_respond; |
718 | } | 765 | } |
719 | } | 766 | } |
@@ -733,30 +780,48 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, | |||
733 | /*If this is a brand new context and we | 780 | /*If this is a brand new context and we |
734 | * haven't started our join process yet, then | 781 | * haven't started our join process yet, then |
735 | * the other node won the race. */ | 782 | * the other node won the race. */ |
736 | response = JOIN_OK_NO_MAP; | 783 | response.packet.code = JOIN_OK_NO_MAP; |
737 | } else if (dlm->joining_node != DLM_LOCK_RES_OWNER_UNKNOWN) { | 784 | } else if (dlm->joining_node != DLM_LOCK_RES_OWNER_UNKNOWN) { |
738 | /* Disallow parallel joins. */ | 785 | /* Disallow parallel joins. */ |
739 | response = JOIN_DISALLOW; | 786 | response.packet.code = JOIN_DISALLOW; |
740 | } else if (dlm->reco.state & DLM_RECO_STATE_ACTIVE) { | 787 | } else if (dlm->reco.state & DLM_RECO_STATE_ACTIVE) { |
741 | mlog(0, "node %u trying to join, but recovery " | 788 | mlog(0, "node %u trying to join, but recovery " |
742 | "is ongoing.\n", bit); | 789 | "is ongoing.\n", bit); |
743 | response = JOIN_DISALLOW; | 790 | response.packet.code = JOIN_DISALLOW; |
744 | } else if (test_bit(bit, dlm->recovery_map)) { | 791 | } else if (test_bit(bit, dlm->recovery_map)) { |
745 | mlog(0, "node %u trying to join, but it " | 792 | mlog(0, "node %u trying to join, but it " |
746 | "still needs recovery.\n", bit); | 793 | "still needs recovery.\n", bit); |
747 | response = JOIN_DISALLOW; | 794 | response.packet.code = JOIN_DISALLOW; |
748 | } else if (test_bit(bit, dlm->domain_map)) { | 795 | } else if (test_bit(bit, dlm->domain_map)) { |
749 | mlog(0, "node %u trying to join, but it " | 796 | mlog(0, "node %u trying to join, but it " |
750 | "is still in the domain! needs recovery?\n", | 797 | "is still in the domain! needs recovery?\n", |
751 | bit); | 798 | bit); |
752 | response = JOIN_DISALLOW; | 799 | response.packet.code = JOIN_DISALLOW; |
753 | } else { | 800 | } else { |
754 | /* Alright we're fully a part of this domain | 801 | /* Alright we're fully a part of this domain |
755 | * so we keep some state as to who's joining | 802 | * so we keep some state as to who's joining |
756 | * and indicate to him that needs to be fixed | 803 | * and indicate to him that needs to be fixed |
757 | * up. */ | 804 | * up. */ |
758 | response = JOIN_OK; | 805 | |
759 | __dlm_set_joining_node(dlm, query->node_idx); | 806 | /* Make sure we speak compatible locking protocols. */ |
807 | if (dlm_query_join_proto_check("DLM", bit, | ||
808 | &dlm->dlm_locking_proto, | ||
809 | &query->dlm_proto)) { | ||
810 | response.packet.code = | ||
811 | JOIN_PROTOCOL_MISMATCH; | ||
812 | } else if (dlm_query_join_proto_check("fs", bit, | ||
813 | &dlm->fs_locking_proto, | ||
814 | &query->fs_proto)) { | ||
815 | response.packet.code = | ||
816 | JOIN_PROTOCOL_MISMATCH; | ||
817 | } else { | ||
818 | response.packet.dlm_minor = | ||
819 | query->dlm_proto.pv_minor; | ||
820 | response.packet.fs_minor = | ||
821 | query->fs_proto.pv_minor; | ||
822 | response.packet.code = JOIN_OK; | ||
823 | __dlm_set_joining_node(dlm, query->node_idx); | ||
824 | } | ||
760 | } | 825 | } |
761 | 826 | ||
762 | spin_unlock(&dlm->spinlock); | 827 | spin_unlock(&dlm->spinlock); |
@@ -765,9 +830,9 @@ unlock_respond: | |||
765 | spin_unlock(&dlm_domain_lock); | 830 | spin_unlock(&dlm_domain_lock); |
766 | 831 | ||
767 | respond: | 832 | respond: |
768 | mlog(0, "We respond with %u\n", response); | 833 | mlog(0, "We respond with %u\n", response.packet.code); |
769 | 834 | ||
770 | return response; | 835 | return response.intval; |
771 | } | 836 | } |
772 | 837 | ||
773 | static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data, | 838 | static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data, |
@@ -899,10 +964,11 @@ static int dlm_send_join_cancels(struct dlm_ctxt *dlm, | |||
899 | 964 | ||
900 | static int dlm_request_join(struct dlm_ctxt *dlm, | 965 | static int dlm_request_join(struct dlm_ctxt *dlm, |
901 | int node, | 966 | int node, |
902 | enum dlm_query_join_response *response) | 967 | enum dlm_query_join_response_code *response) |
903 | { | 968 | { |
904 | int status, retval; | 969 | int status; |
905 | struct dlm_query_join_request join_msg; | 970 | struct dlm_query_join_request join_msg; |
971 | union dlm_query_join_response join_resp; | ||
906 | 972 | ||
907 | mlog(0, "querying node %d\n", node); | 973 | mlog(0, "querying node %d\n", node); |
908 | 974 | ||
@@ -910,12 +976,15 @@ static int dlm_request_join(struct dlm_ctxt *dlm, | |||
910 | join_msg.node_idx = dlm->node_num; | 976 | join_msg.node_idx = dlm->node_num; |
911 | join_msg.name_len = strlen(dlm->name); | 977 | join_msg.name_len = strlen(dlm->name); |
912 | memcpy(join_msg.domain, dlm->name, join_msg.name_len); | 978 | memcpy(join_msg.domain, dlm->name, join_msg.name_len); |
979 | join_msg.dlm_proto = dlm->dlm_locking_proto; | ||
980 | join_msg.fs_proto = dlm->fs_locking_proto; | ||
913 | 981 | ||
914 | /* copy live node map to join message */ | 982 | /* copy live node map to join message */ |
915 | byte_copymap(join_msg.node_map, dlm->live_nodes_map, O2NM_MAX_NODES); | 983 | byte_copymap(join_msg.node_map, dlm->live_nodes_map, O2NM_MAX_NODES); |
916 | 984 | ||
917 | status = o2net_send_message(DLM_QUERY_JOIN_MSG, DLM_MOD_KEY, &join_msg, | 985 | status = o2net_send_message(DLM_QUERY_JOIN_MSG, DLM_MOD_KEY, &join_msg, |
918 | sizeof(join_msg), node, &retval); | 986 | sizeof(join_msg), node, |
987 | &join_resp.intval); | ||
919 | if (status < 0 && status != -ENOPROTOOPT) { | 988 | if (status < 0 && status != -ENOPROTOOPT) { |
920 | mlog_errno(status); | 989 | mlog_errno(status); |
921 | goto bail; | 990 | goto bail; |
@@ -928,14 +997,41 @@ static int dlm_request_join(struct dlm_ctxt *dlm, | |||
928 | if (status == -ENOPROTOOPT) { | 997 | if (status == -ENOPROTOOPT) { |
929 | status = 0; | 998 | status = 0; |
930 | *response = JOIN_OK_NO_MAP; | 999 | *response = JOIN_OK_NO_MAP; |
931 | } else if (retval == JOIN_DISALLOW || | 1000 | } else if (join_resp.packet.code == JOIN_DISALLOW || |
932 | retval == JOIN_OK || | 1001 | join_resp.packet.code == JOIN_OK_NO_MAP) { |
933 | retval == JOIN_OK_NO_MAP) { | 1002 | *response = join_resp.packet.code; |
934 | *response = retval; | 1003 | } else if (join_resp.packet.code == JOIN_PROTOCOL_MISMATCH) { |
1004 | mlog(ML_NOTICE, | ||
1005 | "This node requested DLM locking protocol %u.%u and " | ||
1006 | "filesystem locking protocol %u.%u. At least one of " | ||
1007 | "the protocol versions on node %d is not compatible, " | ||
1008 | "disconnecting\n", | ||
1009 | dlm->dlm_locking_proto.pv_major, | ||
1010 | dlm->dlm_locking_proto.pv_minor, | ||
1011 | dlm->fs_locking_proto.pv_major, | ||
1012 | dlm->fs_locking_proto.pv_minor, | ||
1013 | node); | ||
1014 | status = -EPROTO; | ||
1015 | *response = join_resp.packet.code; | ||
1016 | } else if (join_resp.packet.code == JOIN_OK) { | ||
1017 | *response = join_resp.packet.code; | ||
1018 | /* Use the same locking protocol as the remote node */ | ||
1019 | dlm->dlm_locking_proto.pv_minor = | ||
1020 | join_resp.packet.dlm_minor; | ||
1021 | dlm->fs_locking_proto.pv_minor = | ||
1022 | join_resp.packet.fs_minor; | ||
1023 | mlog(0, | ||
1024 | "Node %d responds JOIN_OK with DLM locking protocol " | ||
1025 | "%u.%u and fs locking protocol %u.%u\n", | ||
1026 | node, | ||
1027 | dlm->dlm_locking_proto.pv_major, | ||
1028 | dlm->dlm_locking_proto.pv_minor, | ||
1029 | dlm->fs_locking_proto.pv_major, | ||
1030 | dlm->fs_locking_proto.pv_minor); | ||
935 | } else { | 1031 | } else { |
936 | status = -EINVAL; | 1032 | status = -EINVAL; |
937 | mlog(ML_ERROR, "invalid response %d from node %u\n", retval, | 1033 | mlog(ML_ERROR, "invalid response %d from node %u\n", |
938 | node); | 1034 | join_resp.packet.code, node); |
939 | } | 1035 | } |
940 | 1036 | ||
941 | mlog(0, "status %d, node %d response is %d\n", status, node, | 1037 | mlog(0, "status %d, node %d response is %d\n", status, node, |
@@ -1008,7 +1104,7 @@ struct domain_join_ctxt { | |||
1008 | 1104 | ||
1009 | static int dlm_should_restart_join(struct dlm_ctxt *dlm, | 1105 | static int dlm_should_restart_join(struct dlm_ctxt *dlm, |
1010 | struct domain_join_ctxt *ctxt, | 1106 | struct domain_join_ctxt *ctxt, |
1011 | enum dlm_query_join_response response) | 1107 | enum dlm_query_join_response_code response) |
1012 | { | 1108 | { |
1013 | int ret; | 1109 | int ret; |
1014 | 1110 | ||
@@ -1034,7 +1130,7 @@ static int dlm_try_to_join_domain(struct dlm_ctxt *dlm) | |||
1034 | { | 1130 | { |
1035 | int status = 0, tmpstat, node; | 1131 | int status = 0, tmpstat, node; |
1036 | struct domain_join_ctxt *ctxt; | 1132 | struct domain_join_ctxt *ctxt; |
1037 | enum dlm_query_join_response response = JOIN_DISALLOW; | 1133 | enum dlm_query_join_response_code response = JOIN_DISALLOW; |
1038 | 1134 | ||
1039 | mlog_entry("%p", dlm); | 1135 | mlog_entry("%p", dlm); |
1040 | 1136 | ||
@@ -1450,10 +1546,38 @@ leave: | |||
1450 | } | 1546 | } |
1451 | 1547 | ||
1452 | /* | 1548 | /* |
1453 | * dlm_register_domain: one-time setup per "domain" | 1549 | * Compare a requested locking protocol version against the current one. |
1550 | * | ||
1551 | * If the major numbers are different, they are incompatible. | ||
1552 | * If the current minor is greater than the request, they are incompatible. | ||
1553 | * If the current minor is less than or equal to the request, they are | ||
1554 | * compatible, and the requester should run at the current minor version. | ||
1555 | */ | ||
1556 | static int dlm_protocol_compare(struct dlm_protocol_version *existing, | ||
1557 | struct dlm_protocol_version *request) | ||
1558 | { | ||
1559 | if (existing->pv_major != request->pv_major) | ||
1560 | return 1; | ||
1561 | |||
1562 | if (existing->pv_minor > request->pv_minor) | ||
1563 | return 1; | ||
1564 | |||
1565 | if (existing->pv_minor < request->pv_minor) | ||
1566 | request->pv_minor = existing->pv_minor; | ||
1567 | |||
1568 | return 0; | ||
1569 | } | ||
1570 | |||
1571 | /* | ||
1572 | * dlm_register_domain: one-time setup per "domain". | ||
1573 | * | ||
1574 | * The filesystem passes in the requested locking version via proto. | ||
1575 | * If registration was successful, proto will contain the negotiated | ||
1576 | * locking protocol. | ||
1454 | */ | 1577 | */ |
1455 | struct dlm_ctxt * dlm_register_domain(const char *domain, | 1578 | struct dlm_ctxt * dlm_register_domain(const char *domain, |
1456 | u32 key) | 1579 | u32 key, |
1580 | struct dlm_protocol_version *fs_proto) | ||
1457 | { | 1581 | { |
1458 | int ret; | 1582 | int ret; |
1459 | struct dlm_ctxt *dlm = NULL; | 1583 | struct dlm_ctxt *dlm = NULL; |
@@ -1496,6 +1620,15 @@ retry: | |||
1496 | goto retry; | 1620 | goto retry; |
1497 | } | 1621 | } |
1498 | 1622 | ||
1623 | if (dlm_protocol_compare(&dlm->fs_locking_proto, fs_proto)) { | ||
1624 | mlog(ML_ERROR, | ||
1625 | "Requested locking protocol version is not " | ||
1626 | "compatible with already registered domain " | ||
1627 | "\"%s\"\n", domain); | ||
1628 | ret = -EPROTO; | ||
1629 | goto leave; | ||
1630 | } | ||
1631 | |||
1499 | __dlm_get(dlm); | 1632 | __dlm_get(dlm); |
1500 | dlm->num_joins++; | 1633 | dlm->num_joins++; |
1501 | 1634 | ||
@@ -1526,6 +1659,13 @@ retry: | |||
1526 | list_add_tail(&dlm->list, &dlm_domains); | 1659 | list_add_tail(&dlm->list, &dlm_domains); |
1527 | spin_unlock(&dlm_domain_lock); | 1660 | spin_unlock(&dlm_domain_lock); |
1528 | 1661 | ||
1662 | /* | ||
1663 | * Pass the locking protocol version into the join. If the join | ||
1664 | * succeeds, it will have the negotiated protocol set. | ||
1665 | */ | ||
1666 | dlm->dlm_locking_proto = dlm_protocol; | ||
1667 | dlm->fs_locking_proto = *fs_proto; | ||
1668 | |||
1529 | ret = dlm_join_domain(dlm); | 1669 | ret = dlm_join_domain(dlm); |
1530 | if (ret) { | 1670 | if (ret) { |
1531 | mlog_errno(ret); | 1671 | mlog_errno(ret); |
@@ -1533,6 +1673,9 @@ retry: | |||
1533 | goto leave; | 1673 | goto leave; |
1534 | } | 1674 | } |
1535 | 1675 | ||
1676 | /* Tell the caller what locking protocol we negotiated */ | ||
1677 | *fs_proto = dlm->fs_locking_proto; | ||
1678 | |||
1536 | ret = 0; | 1679 | ret = 0; |
1537 | leave: | 1680 | leave: |
1538 | if (new_ctxt) | 1681 | if (new_ctxt) |
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c index 6639baab0798..61a000f8524c 100644 --- a/fs/ocfs2/dlm/dlmfs.c +++ b/fs/ocfs2/dlm/dlmfs.c | |||
@@ -60,6 +60,8 @@ | |||
60 | #define MLOG_MASK_PREFIX ML_DLMFS | 60 | #define MLOG_MASK_PREFIX ML_DLMFS |
61 | #include "cluster/masklog.h" | 61 | #include "cluster/masklog.h" |
62 | 62 | ||
63 | #include "ocfs2_lockingver.h" | ||
64 | |||
63 | static const struct super_operations dlmfs_ops; | 65 | static const struct super_operations dlmfs_ops; |
64 | static const struct file_operations dlmfs_file_operations; | 66 | static const struct file_operations dlmfs_file_operations; |
65 | static const struct inode_operations dlmfs_dir_inode_operations; | 67 | static const struct inode_operations dlmfs_dir_inode_operations; |
@@ -70,6 +72,16 @@ static struct kmem_cache *dlmfs_inode_cache; | |||
70 | struct workqueue_struct *user_dlm_worker; | 72 | struct workqueue_struct *user_dlm_worker; |
71 | 73 | ||
72 | /* | 74 | /* |
75 | * This is the userdlmfs locking protocol version. | ||
76 | * | ||
77 | * See fs/ocfs2/dlmglue.c for more details on locking versions. | ||
78 | */ | ||
79 | static const struct dlm_protocol_version user_locking_protocol = { | ||
80 | .pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR, | ||
81 | .pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR, | ||
82 | }; | ||
83 | |||
84 | /* | ||
73 | * decodes a set of open flags into a valid lock level and a set of flags. | 85 | * decodes a set of open flags into a valid lock level and a set of flags. |
74 | * returns < 0 if we have invalid flags | 86 | * returns < 0 if we have invalid flags |
75 | * flags which mean something to us: | 87 | * flags which mean something to us: |
@@ -416,6 +428,7 @@ static int dlmfs_mkdir(struct inode * dir, | |||
416 | struct qstr *domain = &dentry->d_name; | 428 | struct qstr *domain = &dentry->d_name; |
417 | struct dlmfs_inode_private *ip; | 429 | struct dlmfs_inode_private *ip; |
418 | struct dlm_ctxt *dlm; | 430 | struct dlm_ctxt *dlm; |
431 | struct dlm_protocol_version proto = user_locking_protocol; | ||
419 | 432 | ||
420 | mlog(0, "mkdir %.*s\n", domain->len, domain->name); | 433 | mlog(0, "mkdir %.*s\n", domain->len, domain->name); |
421 | 434 | ||
@@ -435,7 +448,7 @@ static int dlmfs_mkdir(struct inode * dir, | |||
435 | 448 | ||
436 | ip = DLMFS_I(inode); | 449 | ip = DLMFS_I(inode); |
437 | 450 | ||
438 | dlm = user_dlm_register_context(domain); | 451 | dlm = user_dlm_register_context(domain, &proto); |
439 | if (IS_ERR(dlm)) { | 452 | if (IS_ERR(dlm)) { |
440 | status = PTR_ERR(dlm); | 453 | status = PTR_ERR(dlm); |
441 | mlog(ML_ERROR, "Error %d could not register domain \"%.*s\"\n", | 454 | mlog(ML_ERROR, "Error %d could not register domain \"%.*s\"\n", |
diff --git a/fs/ocfs2/dlm/userdlm.c b/fs/ocfs2/dlm/userdlm.c index 7d2f578b267d..4cb1d3dae250 100644 --- a/fs/ocfs2/dlm/userdlm.c +++ b/fs/ocfs2/dlm/userdlm.c | |||
@@ -645,7 +645,8 @@ bail: | |||
645 | return status; | 645 | return status; |
646 | } | 646 | } |
647 | 647 | ||
648 | struct dlm_ctxt *user_dlm_register_context(struct qstr *name) | 648 | struct dlm_ctxt *user_dlm_register_context(struct qstr *name, |
649 | struct dlm_protocol_version *proto) | ||
649 | { | 650 | { |
650 | struct dlm_ctxt *dlm; | 651 | struct dlm_ctxt *dlm; |
651 | u32 dlm_key; | 652 | u32 dlm_key; |
@@ -661,7 +662,7 @@ struct dlm_ctxt *user_dlm_register_context(struct qstr *name) | |||
661 | 662 | ||
662 | snprintf(domain, name->len + 1, "%.*s", name->len, name->name); | 663 | snprintf(domain, name->len + 1, "%.*s", name->len, name->name); |
663 | 664 | ||
664 | dlm = dlm_register_domain(domain, dlm_key); | 665 | dlm = dlm_register_domain(domain, dlm_key, proto); |
665 | if (IS_ERR(dlm)) | 666 | if (IS_ERR(dlm)) |
666 | mlog_errno(PTR_ERR(dlm)); | 667 | mlog_errno(PTR_ERR(dlm)); |
667 | 668 | ||
diff --git a/fs/ocfs2/dlm/userdlm.h b/fs/ocfs2/dlm/userdlm.h index c400e93bbf79..39ec27738499 100644 --- a/fs/ocfs2/dlm/userdlm.h +++ b/fs/ocfs2/dlm/userdlm.h | |||
@@ -83,7 +83,8 @@ void user_dlm_write_lvb(struct inode *inode, | |||
83 | void user_dlm_read_lvb(struct inode *inode, | 83 | void user_dlm_read_lvb(struct inode *inode, |
84 | char *val, | 84 | char *val, |
85 | unsigned int len); | 85 | unsigned int len); |
86 | struct dlm_ctxt *user_dlm_register_context(struct qstr *name); | 86 | struct dlm_ctxt *user_dlm_register_context(struct qstr *name, |
87 | struct dlm_protocol_version *proto); | ||
87 | void user_dlm_unregister_context(struct dlm_ctxt *dlm); | 88 | void user_dlm_unregister_context(struct dlm_ctxt *dlm); |
88 | 89 | ||
89 | struct dlmfs_inode_private { | 90 | struct dlmfs_inode_private { |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 3867244fb144..351130c9b734 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <cluster/masklog.h> | 43 | #include <cluster/masklog.h> |
44 | 44 | ||
45 | #include "ocfs2.h" | 45 | #include "ocfs2.h" |
46 | #include "ocfs2_lockingver.h" | ||
46 | 47 | ||
47 | #include "alloc.h" | 48 | #include "alloc.h" |
48 | #include "dcache.h" | 49 | #include "dcache.h" |
@@ -258,6 +259,31 @@ static struct ocfs2_lock_res_ops ocfs2_flock_lops = { | |||
258 | .flags = 0, | 259 | .flags = 0, |
259 | }; | 260 | }; |
260 | 261 | ||
262 | /* | ||
263 | * This is the filesystem locking protocol version. | ||
264 | * | ||
265 | * Whenever the filesystem does new things with locks (adds or removes a | ||
266 | * lock, orders them differently, does different things underneath a lock), | ||
267 | * the version must be changed. The protocol is negotiated when joining | ||
268 | * the dlm domain. A node may join the domain if its major version is | ||
269 | * identical to all other nodes and its minor version is greater than | ||
270 | * or equal to all other nodes. When its minor version is greater than | ||
271 | * the other nodes, it will run at the minor version specified by the | ||
272 | * other nodes. | ||
273 | * | ||
274 | * If a locking change is made that will not be compatible with older | ||
275 | * versions, the major number must be increased and the minor version set | ||
276 | * to zero. If a change merely adds a behavior that can be disabled when | ||
277 | * speaking to older versions, the minor version must be increased. If a | ||
278 | * change adds a fully backwards compatible change (eg, LVB changes that | ||
279 | * are just ignored by older versions), the version does not need to be | ||
280 | * updated. | ||
281 | */ | ||
282 | const struct dlm_protocol_version ocfs2_locking_protocol = { | ||
283 | .pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR, | ||
284 | .pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR, | ||
285 | }; | ||
286 | |||
261 | static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) | 287 | static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) |
262 | { | 288 | { |
263 | return lockres->l_type == OCFS2_LOCK_TYPE_META || | 289 | return lockres->l_type == OCFS2_LOCK_TYPE_META || |
@@ -2506,7 +2532,8 @@ int ocfs2_dlm_init(struct ocfs2_super *osb) | |||
2506 | dlm_key = crc32_le(0, osb->uuid_str, strlen(osb->uuid_str)); | 2532 | dlm_key = crc32_le(0, osb->uuid_str, strlen(osb->uuid_str)); |
2507 | 2533 | ||
2508 | /* for now, uuid == domain */ | 2534 | /* for now, uuid == domain */ |
2509 | dlm = dlm_register_domain(osb->uuid_str, dlm_key); | 2535 | dlm = dlm_register_domain(osb->uuid_str, dlm_key, |
2536 | &osb->osb_locking_proto); | ||
2510 | if (IS_ERR(dlm)) { | 2537 | if (IS_ERR(dlm)) { |
2511 | status = PTR_ERR(dlm); | 2538 | status = PTR_ERR(dlm); |
2512 | mlog_errno(status); | 2539 | mlog_errno(status); |
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h index 5f17243ba501..1d5b0699d0a9 100644 --- a/fs/ocfs2/dlmglue.h +++ b/fs/ocfs2/dlmglue.h | |||
@@ -116,4 +116,5 @@ void ocfs2_wake_downconvert_thread(struct ocfs2_super *osb); | |||
116 | struct ocfs2_dlm_debug *ocfs2_new_dlm_debug(void); | 116 | struct ocfs2_dlm_debug *ocfs2_new_dlm_debug(void); |
117 | void ocfs2_put_dlm_debug(struct ocfs2_dlm_debug *dlm_debug); | 117 | void ocfs2_put_dlm_debug(struct ocfs2_dlm_debug *dlm_debug); |
118 | 118 | ||
119 | extern const struct dlm_protocol_version ocfs2_locking_protocol; | ||
119 | #endif /* DLMGLUE_H */ | 120 | #endif /* DLMGLUE_H */ |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index d08480580470..e8b7292e0152 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
@@ -251,6 +251,7 @@ struct ocfs2_super | |||
251 | struct ocfs2_lock_res osb_rename_lockres; | 251 | struct ocfs2_lock_res osb_rename_lockres; |
252 | struct dlm_eviction_cb osb_eviction_cb; | 252 | struct dlm_eviction_cb osb_eviction_cb; |
253 | struct ocfs2_dlm_debug *osb_dlm_debug; | 253 | struct ocfs2_dlm_debug *osb_dlm_debug; |
254 | struct dlm_protocol_version osb_locking_proto; | ||
254 | 255 | ||
255 | struct dentry *osb_debug_root; | 256 | struct dentry *osb_debug_root; |
256 | 257 | ||
diff --git a/fs/ocfs2/ocfs2_lockingver.h b/fs/ocfs2/ocfs2_lockingver.h new file mode 100644 index 000000000000..82d5eeac0fff --- /dev/null +++ b/fs/ocfs2/ocfs2_lockingver.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* -*- mode: c; c-basic-offset: 8; -*- | ||
2 | * vim: noexpandtab sw=8 ts=8 sts=0: | ||
3 | * | ||
4 | * ocfs2_lockingver.h | ||
5 | * | ||
6 | * Defines OCFS2 Locking version values. | ||
7 | * | ||
8 | * Copyright (C) 2008 Oracle. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public | ||
12 | * License, version 2, as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | */ | ||
19 | |||
20 | #ifndef OCFS2_LOCKINGVER_H | ||
21 | #define OCFS2_LOCKINGVER_H | ||
22 | |||
23 | /* | ||
24 | * The protocol version for ocfs2 cluster locking. See dlmglue.c for | ||
25 | * more details. | ||
26 | */ | ||
27 | #define OCFS2_LOCKING_PROTOCOL_MAJOR 1 | ||
28 | #define OCFS2_LOCKING_PROTOCOL_MINOR 0 | ||
29 | |||
30 | #endif /* OCFS2_LOCKINGVER_H */ | ||
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 01fe40ee5ea9..bec75aff3d9f 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -1355,6 +1355,7 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
1355 | sb->s_fs_info = osb; | 1355 | sb->s_fs_info = osb; |
1356 | sb->s_op = &ocfs2_sops; | 1356 | sb->s_op = &ocfs2_sops; |
1357 | sb->s_export_op = &ocfs2_export_ops; | 1357 | sb->s_export_op = &ocfs2_export_ops; |
1358 | osb->osb_locking_proto = ocfs2_locking_protocol; | ||
1358 | sb->s_time_gran = 1; | 1359 | sb->s_time_gran = 1; |
1359 | sb->s_flags |= MS_NOATIME; | 1360 | sb->s_flags |= MS_NOATIME; |
1360 | /* this is needed to support O_LARGEFILE */ | 1361 | /* this is needed to support O_LARGEFILE */ |
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 739da701ae7b..9a64045ff845 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -319,6 +319,14 @@ void delete_partition(struct gendisk *disk, int part) | |||
319 | put_device(&p->dev); | 319 | put_device(&p->dev); |
320 | } | 320 | } |
321 | 321 | ||
322 | static ssize_t whole_disk_show(struct device *dev, | ||
323 | struct device_attribute *attr, char *buf) | ||
324 | { | ||
325 | return 0; | ||
326 | } | ||
327 | static DEVICE_ATTR(whole_disk, S_IRUSR | S_IRGRP | S_IROTH, | ||
328 | whole_disk_show, NULL); | ||
329 | |||
322 | void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags) | 330 | void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags) |
323 | { | 331 | { |
324 | struct hd_struct *p; | 332 | struct hd_struct *p; |
@@ -352,13 +360,8 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, | |||
352 | device_add(&p->dev); | 360 | device_add(&p->dev); |
353 | partition_sysfs_add_subdir(p); | 361 | partition_sysfs_add_subdir(p); |
354 | p->dev.uevent_suppress = 0; | 362 | p->dev.uevent_suppress = 0; |
355 | if (flags & ADDPART_FLAG_WHOLEDISK) { | 363 | if (flags & ADDPART_FLAG_WHOLEDISK) |
356 | static struct attribute addpartattr = { | 364 | err = device_create_file(&p->dev, &dev_attr_whole_disk); |
357 | .name = "whole_disk", | ||
358 | .mode = S_IRUSR | S_IRGRP | S_IROTH, | ||
359 | }; | ||
360 | err = sysfs_create_file(&p->dev.kobj, &addpartattr); | ||
361 | } | ||
362 | 365 | ||
363 | /* suppress uevent if the disk supresses it */ | 366 | /* suppress uevent if the disk supresses it */ |
364 | if (!disk->dev.uevent_suppress) | 367 | if (!disk->dev.uevent_suppress) |
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index 0871c3dadce1..477904915032 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c | |||
@@ -77,7 +77,12 @@ void sysfs_remove_group(struct kobject * kobj, | |||
77 | 77 | ||
78 | if (grp->name) { | 78 | if (grp->name) { |
79 | sd = sysfs_get_dirent(dir_sd, grp->name); | 79 | sd = sysfs_get_dirent(dir_sd, grp->name); |
80 | BUG_ON(!sd); | 80 | if (!sd) { |
81 | printk(KERN_WARNING "sysfs group %p not found for " | ||
82 | "kobject '%s'\n", grp, kobject_name(kobj)); | ||
83 | WARN_ON(!sd); | ||
84 | return; | ||
85 | } | ||
81 | } else | 86 | } else |
82 | sd = sysfs_get(dir_sd); | 87 | sd = sysfs_get(dir_sd); |
83 | 88 | ||
diff --git a/include/asm-arm/arch-pxa/pxa27x_keyboard.h b/include/asm-arm/arch-pxa/pxa27x_keyboard.h deleted file mode 100644 index 3aaff923b2ca..000000000000 --- a/include/asm-arm/arch-pxa/pxa27x_keyboard.h +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | #define PXAKBD_MAXROW 8 | ||
2 | #define PXAKBD_MAXCOL 8 | ||
3 | |||
4 | struct pxa27x_keyboard_platform_data { | ||
5 | int nr_rows, nr_cols; | ||
6 | int keycodes[PXAKBD_MAXROW][PXAKBD_MAXCOL]; | ||
7 | int gpio_modes[PXAKBD_MAXROW + PXAKBD_MAXCOL]; | ||
8 | |||
9 | #ifdef CONFIG_PM | ||
10 | u32 reg_kpc; | ||
11 | u32 reg_kprec; | ||
12 | #endif | ||
13 | }; | ||
diff --git a/include/asm-arm/arch-pxa/pxa27x_keypad.h b/include/asm-arm/arch-pxa/pxa27x_keypad.h new file mode 100644 index 000000000000..644f7609b523 --- /dev/null +++ b/include/asm-arm/arch-pxa/pxa27x_keypad.h | |||
@@ -0,0 +1,56 @@ | |||
1 | #ifndef __ASM_ARCH_PXA27x_KEYPAD_H | ||
2 | #define __ASM_ARCH_PXA27x_KEYPAD_H | ||
3 | |||
4 | #include <linux/input.h> | ||
5 | |||
6 | #define MAX_MATRIX_KEY_ROWS (8) | ||
7 | #define MAX_MATRIX_KEY_COLS (8) | ||
8 | |||
9 | /* pxa3xx keypad platform specific parameters | ||
10 | * | ||
11 | * NOTE: | ||
12 | * 1. direct_key_num indicates the number of keys in the direct keypad | ||
13 | * _plus_ the number of rotary-encoder sensor inputs, this can be | ||
14 | * left as 0 if only rotary encoders are enabled, the driver will | ||
15 | * automatically calculate this | ||
16 | * | ||
17 | * 2. direct_key_map is the key code map for the direct keys, if rotary | ||
18 | * encoder(s) are enabled, direct key 0/1(2/3) will be ignored | ||
19 | * | ||
20 | * 3. rotary can be either interpreted as a relative input event (e.g. | ||
21 | * REL_WHEEL/REL_HWHEEL) or specific keys (e.g. UP/DOWN/LEFT/RIGHT) | ||
22 | * | ||
23 | * 4. matrix key and direct key will use the same debounce_interval by | ||
24 | * default, which should be sufficient in most cases | ||
25 | */ | ||
26 | struct pxa27x_keypad_platform_data { | ||
27 | |||
28 | /* code map for the matrix keys */ | ||
29 | unsigned int matrix_key_rows; | ||
30 | unsigned int matrix_key_cols; | ||
31 | unsigned int *matrix_key_map; | ||
32 | int matrix_key_map_size; | ||
33 | |||
34 | /* direct keys */ | ||
35 | int direct_key_num; | ||
36 | unsigned int direct_key_map[8]; | ||
37 | |||
38 | /* rotary encoders 0 */ | ||
39 | int enable_rotary0; | ||
40 | int rotary0_rel_code; | ||
41 | int rotary0_up_key; | ||
42 | int rotary0_down_key; | ||
43 | |||
44 | /* rotary encoders 1 */ | ||
45 | int enable_rotary1; | ||
46 | int rotary1_rel_code; | ||
47 | int rotary1_up_key; | ||
48 | int rotary1_down_key; | ||
49 | |||
50 | /* key debounce interval */ | ||
51 | unsigned int debounce_interval; | ||
52 | }; | ||
53 | |||
54 | #define KEY(row, col, val) (((row) << 28) | ((col) << 24) | (val)) | ||
55 | |||
56 | #endif /* __ASM_ARCH_PXA27x_KEYPAD_H */ | ||
diff --git a/include/asm-arm/arch-pxa/tosa.h b/include/asm-arm/arch-pxa/tosa.h index c3364a2c4758..c05e4faf85a6 100644 --- a/include/asm-arm/arch-pxa/tosa.h +++ b/include/asm-arm/arch-pxa/tosa.h | |||
@@ -163,4 +163,34 @@ | |||
163 | 163 | ||
164 | extern struct platform_device tosascoop_jc_device; | 164 | extern struct platform_device tosascoop_jc_device; |
165 | extern struct platform_device tosascoop_device; | 165 | extern struct platform_device tosascoop_device; |
166 | |||
167 | #define TOSA_KEY_SYNC KEY_102ND /* ??? */ | ||
168 | |||
169 | |||
170 | #ifndef CONFIG_KEYBOARD_TOSA_USE_EXT_KEYCODES | ||
171 | #define TOSA_KEY_RECORD KEY_YEN | ||
172 | #define TOSA_KEY_ADDRESSBOOK KEY_KATAKANA | ||
173 | #define TOSA_KEY_CANCEL KEY_ESC | ||
174 | #define TOSA_KEY_CENTER KEY_HIRAGANA | ||
175 | #define TOSA_KEY_OK KEY_HENKAN | ||
176 | #define TOSA_KEY_CALENDAR KEY_KATAKANAHIRAGANA | ||
177 | #define TOSA_KEY_HOMEPAGE KEY_HANGEUL | ||
178 | #define TOSA_KEY_LIGHT KEY_MUHENKAN | ||
179 | #define TOSA_KEY_MENU KEY_HANJA | ||
180 | #define TOSA_KEY_FN KEY_RIGHTALT | ||
181 | #define TOSA_KEY_MAIL KEY_ZENKAKUHANKAKU | ||
182 | #else | ||
183 | #define TOSA_KEY_RECORD KEY_RECORD | ||
184 | #define TOSA_KEY_ADDRESSBOOK KEY_ADDRESSBOOK | ||
185 | #define TOSA_KEY_CANCEL KEY_CANCEL | ||
186 | #define TOSA_KEY_CENTER KEY_SELECT /* ??? */ | ||
187 | #define TOSA_KEY_OK KEY_OK | ||
188 | #define TOSA_KEY_CALENDAR KEY_CALENDAR | ||
189 | #define TOSA_KEY_HOMEPAGE KEY_HOMEPAGE | ||
190 | #define TOSA_KEY_LIGHT KEY_KBDILLUMTOGGLE | ||
191 | #define TOSA_KEY_MENU KEY_MENU | ||
192 | #define TOSA_KEY_FN KEY_FN | ||
193 | #define TOSA_KEY_MAIL KEY_MAIL | ||
194 | #endif | ||
195 | |||
166 | #endif /* _ASM_ARCH_TOSA_H_ */ | 196 | #endif /* _ASM_ARCH_TOSA_H_ */ |
diff --git a/include/linux/input.h b/include/linux/input.h index 056a17a4f34f..1bdc39a8c76c 100644 --- a/include/linux/input.h +++ b/include/linux/input.h | |||
@@ -1020,7 +1020,6 @@ struct ff_effect { | |||
1020 | * @going_away: marks devices that are in a middle of unregistering and | 1020 | * @going_away: marks devices that are in a middle of unregistering and |
1021 | * causes input_open_device*() fail with -ENODEV. | 1021 | * causes input_open_device*() fail with -ENODEV. |
1022 | * @dev: driver model's view of this device | 1022 | * @dev: driver model's view of this device |
1023 | * @cdev: union for struct device pointer | ||
1024 | * @h_list: list of input handles associated with the device. When | 1023 | * @h_list: list of input handles associated with the device. When |
1025 | * accessing the list dev->mutex must be held | 1024 | * accessing the list dev->mutex must be held |
1026 | * @node: used to place the device onto input_dev_list | 1025 | * @node: used to place the device onto input_dev_list |
@@ -1085,9 +1084,6 @@ struct input_dev { | |||
1085 | int going_away; | 1084 | int going_away; |
1086 | 1085 | ||
1087 | struct device dev; | 1086 | struct device dev; |
1088 | union { /* temporarily so while we switching to struct device */ | ||
1089 | struct device *dev; | ||
1090 | } cdev; | ||
1091 | 1087 | ||
1092 | struct list_head h_list; | 1088 | struct list_head h_list; |
1093 | struct list_head node; | 1089 | struct list_head node; |
@@ -1311,6 +1307,9 @@ static inline void input_set_abs_params(struct input_dev *dev, int axis, int min | |||
1311 | dev->absbit[BIT_WORD(axis)] |= BIT_MASK(axis); | 1307 | dev->absbit[BIT_WORD(axis)] |= BIT_MASK(axis); |
1312 | } | 1308 | } |
1313 | 1309 | ||
1310 | int input_get_keycode(struct input_dev *dev, int scancode, int *keycode); | ||
1311 | int input_set_keycode(struct input_dev *dev, int scancode, int keycode); | ||
1312 | |||
1314 | extern struct class input_class; | 1313 | extern struct class input_class; |
1315 | 1314 | ||
1316 | /** | 1315 | /** |