Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0a4e1aa authored by Kristoffer Ericson's avatar Kristoffer Ericson Committed by Dmitry Torokhov
Browse files

Input: add support for HP Jornada 7xx onboard keyboard



The driver supports onboard keyboards of HP Jornada 710/720/728

Signed-off-by: default avatarKristoffer Ericson <kristoffer.ericson@gmail.com>
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent 2aa2cb9e
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -219,6 +219,16 @@ config KEYBOARD_HP6XX
	  To compile this driver as a module, choose M here: the
	  module will be called jornada680_kbd.

config KEYBOARD_HP7XX
	tristate "HP Jornada 7XX Keyboard Driver"
	depends on SA1100_JORNADA720_SSP && SA1100_SSP
	help
	  Say Y here to add support for the HP Jornada 7xx (710/720/728)
	  onboard keyboard.

	  To compile this driver as a module, choose M here: the
	  module will be called jornada720_kbd.

config KEYBOARD_OMAP
	tristate "TI OMAP keypad support"
	depends on (ARCH_OMAP1 || ARCH_OMAP2)
+1 −0
Original line number Diff line number Diff line
@@ -22,4 +22,5 @@ obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o
obj-$(CONFIG_KEYBOARD_AAED2000)		+= aaed2000_kbd.o
obj-$(CONFIG_KEYBOARD_GPIO)		+= gpio_keys.o
obj-$(CONFIG_KEYBOARD_HP6XX)		+= jornada680_kbd.o
obj-$(CONFIG_KEYBOARD_HP7XX)		+= jornada720_kbd.o
+181 −0
Original line number Diff line number Diff line
/*
 * 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);