diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-04-08 03:00:33 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-04-08 03:00:33 -0400 |
commit | ba28f22e7cf16cb310bb491cbb3f7d0d5d1f5c5d (patch) | |
tree | 6d58e91731385281436da191e82c56cd1627482f /drivers/input/keyboard | |
parent | 577c9c456f0e1371cbade38eaf91ae8e8a308555 (diff) | |
parent | 59cc1dd97ca9ac0363ef2f770901fbd86e2b970a (diff) |
Merge branch 'next' into for-linus
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r-- | drivers/input/keyboard/atkbd.c | 135 | ||||
-rw-r--r-- | drivers/input/keyboard/bf54x-keys.c | 4 | ||||
-rw-r--r-- | drivers/input/keyboard/hilkbd.c | 140 |
3 files changed, 144 insertions, 135 deletions
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 45470f18d7e9..f999dc60c3b8 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -229,7 +229,8 @@ struct atkbd { | |||
229 | /* | 229 | /* |
230 | * System-specific ketymap fixup routine | 230 | * System-specific ketymap fixup routine |
231 | */ | 231 | */ |
232 | static void (*atkbd_platform_fixup)(struct atkbd *); | 232 | static void (*atkbd_platform_fixup)(struct atkbd *, const void *data); |
233 | static void *atkbd_platform_fixup_data; | ||
233 | 234 | ||
234 | static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, | 235 | static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, |
235 | ssize_t (*handler)(struct atkbd *, char *)); | 236 | ssize_t (*handler)(struct atkbd *, char *)); |
@@ -834,87 +835,64 @@ static void atkbd_disconnect(struct serio *serio) | |||
834 | } | 835 | } |
835 | 836 | ||
836 | /* | 837 | /* |
837 | * Most special keys (Fn+F?) on Dell laptops do not generate release | 838 | * generate release events for the keycodes given in data |
838 | * events so we have to do it ourselves. | ||
839 | */ | 839 | */ |
840 | static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) | 840 | static void atkbd_apply_forced_release_keylist(struct atkbd* atkbd, |
841 | const void *data) | ||
841 | { | 842 | { |
842 | static const unsigned int forced_release_keys[] = { | 843 | const unsigned int *keys = data; |
843 | 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, | 844 | unsigned int i; |
844 | }; | ||
845 | int i; | ||
846 | 845 | ||
847 | if (atkbd->set == 2) | 846 | if (atkbd->set == 2) |
848 | for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) | 847 | for (i = 0; keys[i] != -1U; i++) |
849 | __set_bit(forced_release_keys[i], | 848 | __set_bit(keys[i], atkbd->force_release_mask); |
850 | atkbd->force_release_mask); | ||
851 | } | 849 | } |
852 | 850 | ||
853 | /* | 851 | /* |
852 | * Most special keys (Fn+F?) on Dell laptops do not generate release | ||
853 | * events so we have to do it ourselves. | ||
854 | */ | ||
855 | static unsigned int atkbd_dell_laptop_forced_release_keys[] = { | ||
856 | 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, -1U | ||
857 | }; | ||
858 | |||
859 | /* | ||
854 | * Perform fixup for HP system that doesn't generate release | 860 | * Perform fixup for HP system that doesn't generate release |
855 | * for its video switch | 861 | * for its video switch |
856 | */ | 862 | */ |
857 | static void atkbd_hp_keymap_fixup(struct atkbd *atkbd) | 863 | static unsigned int atkbd_hp_forced_release_keys[] = { |
858 | { | 864 | 0x94, -1U |
859 | static const unsigned int forced_release_keys[] = { | 865 | }; |
860 | 0x94, | ||
861 | }; | ||
862 | int i; | ||
863 | |||
864 | if (atkbd->set == 2) | ||
865 | for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) | ||
866 | __set_bit(forced_release_keys[i], | ||
867 | atkbd->force_release_mask); | ||
868 | } | ||
869 | 866 | ||
870 | /* | 867 | /* |
871 | * Inventec system with broken key release on volume keys | 868 | * Inventec system with broken key release on volume keys |
872 | */ | 869 | */ |
873 | static void atkbd_inventec_keymap_fixup(struct atkbd *atkbd) | 870 | static unsigned int atkbd_inventec_forced_release_keys[] = { |
874 | { | 871 | 0xae, 0xb0, -1U |
875 | const unsigned int forced_release_keys[] = { | 872 | }; |
876 | 0xae, 0xb0, | ||
877 | }; | ||
878 | int i; | ||
879 | |||
880 | if (atkbd->set == 2) | ||
881 | for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) | ||
882 | __set_bit(forced_release_keys[i], | ||
883 | atkbd->force_release_mask); | ||
884 | } | ||
885 | 873 | ||
886 | /* | 874 | /* |
887 | * Perform fixup for HP Pavilion ZV6100 laptop that doesn't generate release | 875 | * Perform fixup for HP Pavilion ZV6100 laptop that doesn't generate release |
888 | * for its volume buttons | 876 | * for its volume buttons |
889 | */ | 877 | */ |
890 | static void atkbd_hp_zv6100_keymap_fixup(struct atkbd *atkbd) | 878 | static unsigned int atkbd_hp_zv6100_forced_release_keys[] = { |
891 | { | 879 | 0xae, 0xb0, -1U |
892 | const unsigned int forced_release_keys[] = { | 880 | }; |
893 | 0xae, 0xb0, | ||
894 | }; | ||
895 | int i; | ||
896 | |||
897 | if (atkbd->set == 2) | ||
898 | for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) | ||
899 | __set_bit(forced_release_keys[i], | ||
900 | atkbd->force_release_mask); | ||
901 | } | ||
902 | 881 | ||
903 | /* | 882 | /* |
904 | * Samsung NC10 with Fn+F? key release not working | 883 | * Samsung NC10 with Fn+F? key release not working |
905 | */ | 884 | */ |
906 | static void atkbd_samsung_keymap_fixup(struct atkbd *atkbd) | 885 | static unsigned int atkbd_samsung_forced_release_keys[] = { |
907 | { | 886 | 0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9, -1U |
908 | const unsigned int forced_release_keys[] = { | 887 | }; |
909 | 0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9, | ||
910 | }; | ||
911 | int i; | ||
912 | 888 | ||
913 | if (atkbd->set == 2) | 889 | /* |
914 | for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) | 890 | * The volume up and volume down special keys on a Fujitsu Amilo PA 1510 laptop |
915 | __set_bit(forced_release_keys[i], | 891 | * do not generate release events so we have to do it ourselves. |
916 | atkbd->force_release_mask); | 892 | */ |
917 | } | 893 | static unsigned int atkbd_amilo_pa1510_forced_release_keys[] = { |
894 | 0xb0, 0xae, -1U | ||
895 | }; | ||
918 | 896 | ||
919 | /* | 897 | /* |
920 | * atkbd_set_keycode_table() initializes keyboard's keycode table | 898 | * atkbd_set_keycode_table() initializes keyboard's keycode table |
@@ -967,7 +945,7 @@ static void atkbd_set_keycode_table(struct atkbd *atkbd) | |||
967 | * Perform additional fixups | 945 | * Perform additional fixups |
968 | */ | 946 | */ |
969 | if (atkbd_platform_fixup) | 947 | if (atkbd_platform_fixup) |
970 | atkbd_platform_fixup(atkbd); | 948 | atkbd_platform_fixup(atkbd, atkbd_platform_fixup_data); |
971 | } | 949 | } |
972 | 950 | ||
973 | /* | 951 | /* |
@@ -1492,9 +1470,11 @@ static ssize_t atkbd_show_err_count(struct atkbd *atkbd, char *buf) | |||
1492 | return sprintf(buf, "%lu\n", atkbd->err_count); | 1470 | return sprintf(buf, "%lu\n", atkbd->err_count); |
1493 | } | 1471 | } |
1494 | 1472 | ||
1495 | static int __init atkbd_setup_fixup(const struct dmi_system_id *id) | 1473 | static int __init atkbd_setup_forced_release(const struct dmi_system_id *id) |
1496 | { | 1474 | { |
1497 | atkbd_platform_fixup = id->driver_data; | 1475 | atkbd_platform_fixup = atkbd_apply_forced_release_keylist; |
1476 | atkbd_platform_fixup_data = id->driver_data; | ||
1477 | |||
1498 | return 0; | 1478 | return 0; |
1499 | } | 1479 | } |
1500 | 1480 | ||
@@ -1505,8 +1485,8 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1505 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 1485 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
1506 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ | 1486 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ |
1507 | }, | 1487 | }, |
1508 | .callback = atkbd_setup_fixup, | 1488 | .callback = atkbd_setup_forced_release, |
1509 | .driver_data = atkbd_dell_laptop_keymap_fixup, | 1489 | .driver_data = atkbd_dell_laptop_forced_release_keys, |
1510 | }, | 1490 | }, |
1511 | { | 1491 | { |
1512 | .ident = "Dell Laptop", | 1492 | .ident = "Dell Laptop", |
@@ -1514,8 +1494,8 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1514 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), | 1494 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), |
1515 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ | 1495 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ |
1516 | }, | 1496 | }, |
1517 | .callback = atkbd_setup_fixup, | 1497 | .callback = atkbd_setup_forced_release, |
1518 | .driver_data = atkbd_dell_laptop_keymap_fixup, | 1498 | .driver_data = atkbd_dell_laptop_forced_release_keys, |
1519 | }, | 1499 | }, |
1520 | { | 1500 | { |
1521 | .ident = "HP 2133", | 1501 | .ident = "HP 2133", |
@@ -1523,8 +1503,8 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1523 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 1503 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
1524 | DMI_MATCH(DMI_PRODUCT_NAME, "HP 2133"), | 1504 | DMI_MATCH(DMI_PRODUCT_NAME, "HP 2133"), |
1525 | }, | 1505 | }, |
1526 | .callback = atkbd_setup_fixup, | 1506 | .callback = atkbd_setup_forced_release, |
1527 | .driver_data = atkbd_hp_keymap_fixup, | 1507 | .driver_data = atkbd_hp_forced_release_keys, |
1528 | }, | 1508 | }, |
1529 | { | 1509 | { |
1530 | .ident = "HP Pavilion ZV6100", | 1510 | .ident = "HP Pavilion ZV6100", |
@@ -1532,8 +1512,8 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1532 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 1512 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
1533 | DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"), | 1513 | DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"), |
1534 | }, | 1514 | }, |
1535 | .callback = atkbd_setup_fixup, | 1515 | .callback = atkbd_setup_forced_release, |
1536 | .driver_data = atkbd_hp_zv6100_keymap_fixup, | 1516 | .driver_data = atkbd_hp_zv6100_forced_release_keys, |
1537 | }, | 1517 | }, |
1538 | { | 1518 | { |
1539 | .ident = "Inventec Symphony", | 1519 | .ident = "Inventec Symphony", |
@@ -1541,8 +1521,8 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1541 | DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"), | 1521 | DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"), |
1542 | DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"), | 1522 | DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"), |
1543 | }, | 1523 | }, |
1544 | .callback = atkbd_setup_fixup, | 1524 | .callback = atkbd_setup_forced_release, |
1545 | .driver_data = atkbd_inventec_keymap_fixup, | 1525 | .driver_data = atkbd_inventec_forced_release_keys, |
1546 | }, | 1526 | }, |
1547 | { | 1527 | { |
1548 | .ident = "Samsung NC10", | 1528 | .ident = "Samsung NC10", |
@@ -1550,8 +1530,17 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1550 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), | 1530 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), |
1551 | DMI_MATCH(DMI_PRODUCT_NAME, "NC10"), | 1531 | DMI_MATCH(DMI_PRODUCT_NAME, "NC10"), |
1552 | }, | 1532 | }, |
1553 | .callback = atkbd_setup_fixup, | 1533 | .callback = atkbd_setup_forced_release, |
1554 | .driver_data = atkbd_samsung_keymap_fixup, | 1534 | .driver_data = atkbd_samsung_forced_release_keys, |
1535 | }, | ||
1536 | { | ||
1537 | .ident = "Fujitsu Amilo PA 1510", | ||
1538 | .matches = { | ||
1539 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
1540 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 1510"), | ||
1541 | }, | ||
1542 | .callback = atkbd_setup_forced_release, | ||
1543 | .driver_data = atkbd_amilo_pa1510_forced_release_keys, | ||
1555 | }, | 1544 | }, |
1556 | { } | 1545 | { } |
1557 | }; | 1546 | }; |
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index ee855c5202e8..e94b7d735aca 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c | |||
@@ -211,8 +211,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
211 | 211 | ||
212 | if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || | 212 | if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || |
213 | !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { | 213 | !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { |
214 | printk(KERN_ERR DRV_NAME | 214 | printk(KERN_WARNING DRV_NAME |
215 | ": Invalid Debounce/Columdrive Time from pdata\n"); | 215 | ": Invalid Debounce/Columndrive Time in platform data\n"); |
216 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ | 216 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ |
217 | } else { | 217 | } else { |
218 | bfin_write_KPAD_MSEL( | 218 | bfin_write_KPAD_MSEL( |
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c index aacf71f3cd44..e9d639ec283d 100644 --- a/drivers/input/keyboard/hilkbd.c +++ b/drivers/input/keyboard/hilkbd.c | |||
@@ -198,45 +198,28 @@ static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) | |||
198 | } | 198 | } |
199 | 199 | ||
200 | 200 | ||
201 | /* initialise HIL */ | 201 | /* initialize HIL */ |
202 | static int __init | 202 | static int __devinit hil_keyb_init(void) |
203 | hil_keyb_init(void) | ||
204 | { | 203 | { |
205 | unsigned char c; | 204 | unsigned char c; |
206 | unsigned int i, kbid; | 205 | unsigned int i, kbid; |
207 | wait_queue_head_t hil_wait; | 206 | wait_queue_head_t hil_wait; |
208 | int err; | 207 | int err; |
209 | 208 | ||
210 | if (hil_dev.dev) { | 209 | if (hil_dev.dev) |
211 | return -ENODEV; /* already initialized */ | 210 | return -ENODEV; /* already initialized */ |
212 | } | ||
213 | 211 | ||
212 | init_waitqueue_head(&hil_wait); | ||
214 | spin_lock_init(&hil_dev.lock); | 213 | spin_lock_init(&hil_dev.lock); |
214 | |||
215 | hil_dev.dev = input_allocate_device(); | 215 | hil_dev.dev = input_allocate_device(); |
216 | if (!hil_dev.dev) | 216 | if (!hil_dev.dev) |
217 | return -ENOMEM; | 217 | return -ENOMEM; |
218 | 218 | ||
219 | #if defined(CONFIG_HP300) | ||
220 | if (!MACH_IS_HP300) { | ||
221 | err = -ENODEV; | ||
222 | goto err1; | ||
223 | } | ||
224 | if (!hwreg_present((void *)(HILBASE + HIL_DATA))) { | ||
225 | printk(KERN_ERR "HIL: hardware register was not found\n"); | ||
226 | err = -ENODEV; | ||
227 | goto err1; | ||
228 | } | ||
229 | if (!request_region(HILBASE + HIL_DATA, 2, "hil")) { | ||
230 | printk(KERN_ERR "HIL: IOPORT region already used\n"); | ||
231 | err = -EIO; | ||
232 | goto err1; | ||
233 | } | ||
234 | #endif | ||
235 | |||
236 | err = request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id); | 219 | err = request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id); |
237 | if (err) { | 220 | if (err) { |
238 | printk(KERN_ERR "HIL: Can't get IRQ\n"); | 221 | printk(KERN_ERR "HIL: Can't get IRQ\n"); |
239 | goto err2; | 222 | goto err1; |
240 | } | 223 | } |
241 | 224 | ||
242 | /* Turn on interrupts */ | 225 | /* Turn on interrupts */ |
@@ -246,11 +229,9 @@ hil_keyb_init(void) | |||
246 | hil_dev.valid = 0; /* clear any pending data */ | 229 | hil_dev.valid = 0; /* clear any pending data */ |
247 | hil_do(HIL_READKBDSADR, NULL, 0); | 230 | hil_do(HIL_READKBDSADR, NULL, 0); |
248 | 231 | ||
249 | init_waitqueue_head(&hil_wait); | 232 | wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3 * HZ); |
250 | wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ); | 233 | if (!hil_dev.valid) |
251 | if (!hil_dev.valid) { | ||
252 | printk(KERN_WARNING "HIL: timed out, assuming no keyboard present\n"); | 234 | printk(KERN_WARNING "HIL: timed out, assuming no keyboard present\n"); |
253 | } | ||
254 | 235 | ||
255 | c = hil_dev.c; | 236 | c = hil_dev.c; |
256 | hil_dev.valid = 0; | 237 | hil_dev.valid = 0; |
@@ -268,7 +249,7 @@ hil_keyb_init(void) | |||
268 | 249 | ||
269 | for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++) | 250 | for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++) |
270 | if (hphilkeyb_keycode[i] != KEY_RESERVED) | 251 | if (hphilkeyb_keycode[i] != KEY_RESERVED) |
271 | set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit); | 252 | __set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit); |
272 | 253 | ||
273 | hil_dev.dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | 254 | hil_dev.dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); |
274 | hil_dev.dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | | 255 | hil_dev.dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | |
@@ -287,34 +268,45 @@ hil_keyb_init(void) | |||
287 | err = input_register_device(hil_dev.dev); | 268 | err = input_register_device(hil_dev.dev); |
288 | if (err) { | 269 | if (err) { |
289 | printk(KERN_ERR "HIL: Can't register device\n"); | 270 | printk(KERN_ERR "HIL: Can't register device\n"); |
290 | goto err3; | 271 | goto err2; |
291 | } | 272 | } |
273 | |||
292 | printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n", | 274 | printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n", |
293 | hil_dev.dev->name, kbid, HILBASE, HIL_IRQ); | 275 | hil_dev.dev->name, kbid, HILBASE, HIL_IRQ); |
294 | 276 | ||
295 | return 0; | 277 | return 0; |
296 | 278 | ||
297 | err3: | 279 | err2: |
298 | hil_do(HIL_INTOFF, NULL, 0); | 280 | hil_do(HIL_INTOFF, NULL, 0); |
299 | disable_irq(HIL_IRQ); | ||
300 | free_irq(HIL_IRQ, hil_dev.dev_id); | 281 | free_irq(HIL_IRQ, hil_dev.dev_id); |
301 | err2: | ||
302 | #if defined(CONFIG_HP300) | ||
303 | release_region(HILBASE + HIL_DATA, 2); | ||
304 | err1: | 282 | err1: |
305 | #endif | ||
306 | input_free_device(hil_dev.dev); | 283 | input_free_device(hil_dev.dev); |
307 | hil_dev.dev = NULL; | 284 | hil_dev.dev = NULL; |
308 | return err; | 285 | return err; |
309 | } | 286 | } |
310 | 287 | ||
288 | static void __devexit hil_keyb_exit(void) | ||
289 | { | ||
290 | if (HIL_IRQ) | ||
291 | free_irq(HIL_IRQ, hil_dev.dev_id); | ||
292 | |||
293 | /* Turn off interrupts */ | ||
294 | hil_do(HIL_INTOFF, NULL, 0); | ||
295 | |||
296 | input_unregister_device(hil_dev.dev); | ||
297 | hil_dev.dev = NULL; | ||
298 | } | ||
311 | 299 | ||
312 | #if defined(CONFIG_PARISC) | 300 | #if defined(CONFIG_PARISC) |
313 | static int __init | 301 | static int __devinit hil_probe_chip(struct parisc_device *dev) |
314 | hil_init_chip(struct parisc_device *dev) | ||
315 | { | 302 | { |
303 | /* Only allow one HIL keyboard */ | ||
304 | if (hil_dev.dev) | ||
305 | return -ENODEV; | ||
306 | |||
316 | if (!dev->irq) { | 307 | if (!dev->irq) { |
317 | printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa.start); | 308 | printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%p\n", |
309 | (void *)dev->hpa.start); | ||
318 | return -ENODEV; | 310 | return -ENODEV; |
319 | } | 311 | } |
320 | 312 | ||
@@ -327,51 +319,79 @@ hil_init_chip(struct parisc_device *dev) | |||
327 | return hil_keyb_init(); | 319 | return hil_keyb_init(); |
328 | } | 320 | } |
329 | 321 | ||
322 | static int __devexit hil_remove_chip(struct parisc_device *dev) | ||
323 | { | ||
324 | hil_keyb_exit(); | ||
325 | |||
326 | return 0; | ||
327 | } | ||
328 | |||
330 | static struct parisc_device_id hil_tbl[] = { | 329 | static struct parisc_device_id hil_tbl[] = { |
331 | { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 }, | 330 | { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 }, |
332 | { 0, } | 331 | { 0, } |
333 | }; | 332 | }; |
334 | 333 | ||
334 | #if 0 | ||
335 | /* Disabled to avoid conflicts with the HP SDC HIL drivers */ | ||
335 | MODULE_DEVICE_TABLE(parisc, hil_tbl); | 336 | MODULE_DEVICE_TABLE(parisc, hil_tbl); |
337 | #endif | ||
336 | 338 | ||
337 | static struct parisc_driver hil_driver = { | 339 | static struct parisc_driver hil_driver = { |
338 | .name = "hil", | 340 | .name = "hil", |
339 | .id_table = hil_tbl, | 341 | .id_table = hil_tbl, |
340 | .probe = hil_init_chip, | 342 | .probe = hil_probe_chip, |
343 | .remove = __devexit_p(hil_remove_chip), | ||
341 | }; | 344 | }; |
342 | #endif /* CONFIG_PARISC */ | ||
343 | |||
344 | 345 | ||
345 | static int __init hil_init(void) | 346 | static int __init hil_init(void) |
346 | { | 347 | { |
347 | #if defined(CONFIG_PARISC) | ||
348 | return register_parisc_driver(&hil_driver); | 348 | return register_parisc_driver(&hil_driver); |
349 | #else | ||
350 | return hil_keyb_init(); | ||
351 | #endif | ||
352 | } | 349 | } |
353 | 350 | ||
354 | |||
355 | static void __exit hil_exit(void) | 351 | static void __exit hil_exit(void) |
356 | { | 352 | { |
357 | if (HIL_IRQ) { | 353 | unregister_parisc_driver(&hil_driver); |
358 | disable_irq(HIL_IRQ); | 354 | } |
359 | free_irq(HIL_IRQ, hil_dev.dev_id); | 355 | |
356 | #else /* !CONFIG_PARISC */ | ||
357 | |||
358 | static int __init hil_init(void) | ||
359 | { | ||
360 | int error; | ||
361 | |||
362 | /* Only allow one HIL keyboard */ | ||
363 | if (hil_dev.dev) | ||
364 | return -EBUSY; | ||
365 | |||
366 | if (!MACH_IS_HP300) | ||
367 | return -ENODEV; | ||
368 | |||
369 | if (!hwreg_present((void *)(HILBASE + HIL_DATA))) { | ||
370 | printk(KERN_ERR "HIL: hardware register was not found\n"); | ||
371 | return -ENODEV; | ||
360 | } | 372 | } |
361 | 373 | ||
362 | /* Turn off interrupts */ | 374 | if (!request_region(HILBASE + HIL_DATA, 2, "hil")) { |
363 | hil_do(HIL_INTOFF, NULL, 0); | 375 | printk(KERN_ERR "HIL: IOPORT region already used\n"); |
376 | return -EIO; | ||
377 | } | ||
364 | 378 | ||
365 | input_unregister_device(hil_dev.dev); | 379 | error = hil_keyb_init(); |
380 | if (error) { | ||
381 | release_region(HILBASE + HIL_DATA, 2); | ||
382 | return error; | ||
383 | } | ||
366 | 384 | ||
367 | hil_dev.dev = NULL; | 385 | return 0; |
386 | } | ||
368 | 387 | ||
369 | #if defined(CONFIG_PARISC) | 388 | static void __exit hil_exit(void) |
370 | unregister_parisc_driver(&hil_driver); | 389 | { |
371 | #else | 390 | hil_keyb_exit(); |
372 | release_region(HILBASE+HIL_DATA, 2); | 391 | release_region(HILBASE + HIL_DATA, 2); |
373 | #endif | ||
374 | } | 392 | } |
375 | 393 | ||
394 | #endif /* CONFIG_PARISC */ | ||
395 | |||
376 | module_init(hil_init); | 396 | module_init(hil_init); |
377 | module_exit(hil_exit); | 397 | module_exit(hil_exit); |