-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Input: add support for HP Jornada 7xx onboard keyboard
The driver supports onboard keyboards of HP Jornada 710/720/728 Signed-off-by: Kristoffer Ericson <kristoffer.ericson@gmail.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
- Loading branch information
Kristoffer Ericson
authored and
Dmitry Torokhov
committed
Sep 26, 2007
1 parent
2aa2cb9
commit b0a4e1a
Showing
3 changed files
with
192 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
/* | ||
* drivers/input/keyboard/jornada720_kbd.c | ||
* | ||
* HP Jornada 720 keyboard platform driver | ||
* | ||
* Copyright (C) 2006/2007 Kristoffer Ericson <Kristoffer.Ericson@Gmail.com> | ||
* | ||
* Copyright (C) 2006 jornada 720 kbd driver by | ||
Filip Zyzniewsk <Filip.Zyzniewski@tefnet.plX | ||
* based on (C) 2004 jornada 720 kbd driver by | ||
Alex Lange <chicken@handhelds.org> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
*/ | ||
#include <linux/device.h> | ||
#include <linux/errno.h> | ||
#include <linux/init.h> | ||
#include <linux/interrupt.h> | ||
#include <linux/init.h> | ||
#include <linux/input.h> | ||
#include <linux/kernel.h> | ||
#include <linux/module.h> | ||
#include <linux/platform_device.h> | ||
|
||
#include <asm/arch/jornada720.h> | ||
#include <asm/hardware.h> | ||
|
||
MODULE_AUTHOR("Kristoffer Ericson <Kristoffer.Ericson@gmail.com>"); | ||
MODULE_DESCRIPTION("HP Jornada 710/720/728 keyboard driver"); | ||
MODULE_LICENSE("GPLv2"); | ||
|
||
static unsigned short jornada_std_keymap[128] = { /* ROW */ | ||
0, KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, /* #1 */ | ||
KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE, /* -> */ | ||
0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, /* #2 */ | ||
KEY_0, KEY_MINUS, KEY_EQUAL,0, 0, 0, /* -> */ | ||
0, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, /* #3 */ | ||
KEY_P, KEY_BACKSLASH, KEY_BACKSPACE, 0, 0, 0, /* -> */ | ||
0, KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, /* #4 */ | ||
KEY_SEMICOLON, KEY_LEFTBRACE, KEY_RIGHTBRACE, 0, 0, 0, /* -> */ | ||
0, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_COMMA, /* #5 */ | ||
KEY_DOT, KEY_KPMINUS, KEY_APOSTROPHE, KEY_ENTER, 0, 0,0, /* -> */ | ||
0, KEY_TAB, 0, KEY_LEFTSHIFT, 0, KEY_APOSTROPHE, 0, 0, 0, 0, /* #6 */ | ||
KEY_UP, 0, KEY_RIGHTSHIFT, 0, 0, 0,0, 0, 0, 0, 0, KEY_LEFTALT, KEY_GRAVE, /* -> */ | ||
0, 0, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0,0, KEY_KPASTERISK, /* -> */ | ||
KEY_LEFTCTRL, 0, KEY_SPACE, 0, 0, 0, KEY_SLASH, KEY_DELETE, 0, 0, /* -> */ | ||
0, 0, 0, KEY_POWER, /* -> */ | ||
}; | ||
|
||
struct jornadakbd { | ||
unsigned short keymap[ARRAY_SIZE(jornada_std_keymap)]; | ||
struct input_dev *input; | ||
}; | ||
|
||
static irqreturn_t jornada720_kbd_interrupt(int irq, void *dev_id) | ||
{ | ||
struct platform_device *pdev = dev_id; | ||
struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); | ||
u8 count, kbd_data; | ||
|
||
/* startup ssp with spinlock */ | ||
jornada_ssp_start(); | ||
|
||
if (jornada_ssp_inout(GETSCANKEYCODE) != TXDUMMY) { | ||
printk(KERN_DEBUG | ||
"jornada720_kbd: " | ||
"GetKeycode command failed with ETIMEDOUT, " | ||
"flushed bus\n"); | ||
} else { | ||
/* How many keycodes are waiting for us? */ | ||
count = jornada_ssp_byte(TXDUMMY); | ||
|
||
/* Lets drag them out one at a time */ | ||
while (count--) { | ||
/* Exchange TxDummy for location (keymap[kbddata]) */ | ||
kbd_data = jornada_ssp_byte(TXDUMMY); | ||
|
||
input_report_key(jornadakbd->input, | ||
jornadakbd->keymap[kbd_data & 0x7f], | ||
!(kbd_data & 0x80)); | ||
input_sync(jornadakbd->input); | ||
} | ||
} | ||
|
||
/* release spinlock and turn off ssp */ | ||
jornada_ssp_end(); | ||
|
||
return IRQ_HANDLED; | ||
}; | ||
|
||
static int __devinit jornada720_kbd_probe(struct platform_device *pdev) | ||
{ | ||
struct jornadakbd *jornadakbd; | ||
struct input_dev *input_dev; | ||
int i, err; | ||
|
||
jornadakbd = kzalloc(sizeof(struct jornadakbd), GFP_KERNEL); | ||
input_dev = input_allocate_device(); | ||
if (!jornadakbd || !input_dev) { | ||
err = -ENOMEM; | ||
goto fail1; | ||
} | ||
|
||
platform_set_drvdata(pdev, jornadakbd); | ||
|
||
memcpy(jornadakbd->keymap, jornada_std_keymap, | ||
sizeof(jornada_std_keymap)); | ||
jornadakbd->input = input_dev; | ||
|
||
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
input_dev->name = "HP Jornada 720 keyboard"; | ||
input_dev->phys = "jornadakbd/input0"; | ||
input_dev->keycode = jornadakbd->keymap; | ||
input_dev->keycodesize = sizeof(unsigned short); | ||
input_dev->keycodemax = ARRAY_SIZE(jornada_std_keymap); | ||
input_dev->id.bustype = BUS_HOST; | ||
input_dev->dev.parent = &pdev->dev; | ||
|
||
for (i = 0; i < ARRAY_SIZE(jornadakbd->keymap); i++) | ||
__set_bit(jornadakbd->keymap[i], input_dev->keybit); | ||
__clear_bit(KEY_RESERVED, input_dev->keybit); | ||
|
||
err = request_irq(IRQ_GPIO0, | ||
jornada720_kbd_interrupt, | ||
IRQF_DISABLED | IRQF_TRIGGER_FALLING, | ||
"jornadakbd", pdev); | ||
if (err) { | ||
printk(KERN_INFO "jornadakbd720_kbd: Unable to grab IRQ\n"); | ||
goto fail1; | ||
} | ||
|
||
err = input_register_device(jornadakbd->input); | ||
if (err) | ||
goto fail2; | ||
|
||
return 0; | ||
|
||
fail2: /* IRQ, DEVICE, MEMORY */ | ||
free_irq(IRQ_GPIO0, pdev); | ||
fail1: /* DEVICE, MEMORY */ | ||
platform_set_drvdata(pdev, NULL); | ||
input_free_device(input_dev); | ||
kfree(jornadakbd); | ||
return err; | ||
}; | ||
|
||
static int __devexit jornada720_kbd_remove(struct platform_device *pdev) | ||
{ | ||
struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); | ||
|
||
free_irq(IRQ_GPIO0, pdev); | ||
platform_set_drvdata(pdev, NULL); | ||
input_unregister_device(jornadakbd->input); | ||
kfree(jornadakbd); | ||
|
||
return 0; | ||
} | ||
|
||
static struct platform_driver jornada720_kbd_driver = { | ||
.driver = { | ||
.name = "jornada720_kbd", | ||
}, | ||
.probe = jornada720_kbd_probe, | ||
.remove = __devexit_p(jornada720_kbd_remove), | ||
}; | ||
|
||
static int __init jornada720_kbd_init(void) | ||
{ | ||
return platform_driver_register(&jornada720_kbd_driver); | ||
} | ||
|
||
static void __exit jornada720_kbd_exit(void) | ||
{ | ||
platform_driver_unregister(&jornada720_kbd_driver); | ||
} | ||
|
||
module_init(jornada720_kbd_init); | ||
module_exit(jornada720_kbd_exit); |