Commit 2c01e7bc authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input layer updates from Dmitry Torokhov:
 - a bunch of new drivers (DA9052/53 touchscreenn controller, Synaptics
   Navpoint, LM8333 keypads, Wacom I2C touhscreen);
 - updates to existing touchpad drivers (ALPS, Sntelic);
 - Wacom driver now supports Intuos5;
 - device-tree bindings in numerous drivers;
 - other cleanups and fixes.

Fix annoying conflict in drivers/input/tablet/wacom_wac.c that I think
implies that the input layer device naming is broken, but let's see.  I
brough it up with Dmitry.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (57 commits)
  Input: matrix-keymap - fix building keymaps
  Input: spear-keyboard - document DT bindings
  Input: spear-keyboard - add device tree bindings
  Input: matrix-keymap - wire up device tree support
  Input: matrix-keymap - uninline and prepare for device tree support
  Input: adp5588 - add support for gpio names
  Input: omap-keypad - dynamically handle register offsets
  Input: synaptics - fix compile warning
  MAINTAINERS: adjust input-related patterns
  Input: ALPS - switch to using input_mt_report_finger_count
  Input: ALPS - add semi-MT support for v4 protocol
  Input: Add Synaptics NavPoint (PXA27x SSP/SPI) driver
  Input: atmel_mxt_ts - dump each message on just 1 line
  Input: atmel_mxt_ts - do not read extra (checksum) byte
  Input: atmel_mxt_ts - verify object size in mxt_write_object
  Input: atmel_mxt_ts - only allow root to update firmware
  Input: atmel_mxt_ts - use CONFIG_PM_SLEEP
  Input: sentelic - report device's production serial number
  Input: tl6040-vibra - Device Tree support
  Input: evdev - properly handle read/write with count 0
  ...
parents ab11ca34 e644dae6
......@@ -23,9 +23,10 @@ Contact: linux-input@vger.kernel.org
Description:
Attribute group for control of the status LEDs and the OLEDs.
This attribute group is only available for Intuos 4 M, L,
and XL (with LEDs and OLEDs) and Cintiq 21UX2 and Cintiq 24HD
(LEDs only). Therefore its presence implicitly signifies the
presence of said LEDs and OLEDs on the tablet device.
and XL (with LEDs and OLEDs), Intuos 5 (LEDs only), and Cintiq
21UX2 and Cintiq 24HD (LEDs only). Therefore its presence
implicitly signifies the presence of said LEDs and OLEDs on the
tablet device.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status0_luminance
Date: August 2011
......@@ -48,10 +49,10 @@ What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led0
Date: August 2011
Contact: linux-input@vger.kernel.org
Description:
Writing to this file sets which one of the four (for Intuos 4)
or of the right four (for Cintiq 21UX2 and Cintiq 24HD) status
LEDs is active (0..3). The other three LEDs on the same side are
always inactive.
Writing to this file sets which one of the four (for Intuos 4
and Intuos 5) or of the right four (for Cintiq 21UX2 and Cintiq
24HD) status LEDs is active (0..3). The other three LEDs on the
same side are always inactive.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led1_select
Date: September 2011
......
* SPEAr keyboard controller
Required properties:
- compatible: "st,spear300-kbd"
Optional properties, in addition to those specified by the shared
matrix-keyboard bindings:
- autorepeat: bool: enables key autorepeat
- st,mode: keyboard mode: 0 - 9x9, 1 - 6x6, 2 - 2x2
Example:
kbd@fc400000 {
compatible = "st,spear300-kbd";
reg = <0xfc400000 0x100>;
linux,keymap = < 0x00030012
0x0102003a >;
autorepeat;
st,mode = <0>;
};
* NXP LPC32xx SoC Touchscreen Controller (TSC)
Required properties:
- compatible: must be "nxp,lpc3220-tsc"
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: The TSC/ADC interrupt
Example:
tsc@40048000 {
compatible = "nxp,lpc3220-tsc";
reg = <0x40048000 0x1000>;
interrupt-parent = <&mic>;
interrupts = <39 0>;
};
Vibra driver for the twl6040 family
The vibra driver is a child of the twl6040 MFD dirver.
Documentation/devicetree/bindings/mfd/twl6040.txt
Required properties:
- compatible : Must be "ti,twl6040-vibra";
- interrupts: 4, Vibra overcurrent interrupt
- vddvibl-supply: Regulator supplying the left vibra motor
- vddvibr-supply: Regulator supplying the right vibra motor
- vibldrv_res: Board specific left driver resistance
- vibrdrv_res: Board specific right driver resistance
- viblmotor_res: Board specific left motor resistance
- vibrmotor_res: Board specific right motor resistance
Optional properties:
- vddvibl_uV: If the vddvibl default voltage need to be changed
- vddvibr_uV: If the vddvibr default voltage need to be changed
Example:
/*
* 8-channel high quality low-power audio codec
* http://www.ti.com/lit/ds/symlink/twl6040.pdf
*/
twl6040: twl6040@4b {
...
twl6040_vibra: twl6040@1 {
compatible = "ti,twl6040-vibra";
interrupts = <4>;
vddvibl-supply = <&vbat>;
vddvibr-supply = <&vbat>;
vibldrv_res = <8>;
vibrdrv_res = <3>;
viblmotor_res = <10>;
vibrmotor_res = <10>;
};
};
......@@ -3465,6 +3465,8 @@ Q: http://patchwork.kernel.org/project/linux-input/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git
S: Maintained
F: drivers/input/
F: include/linux/input.h
F: include/linux/input/
INPUT MULTITOUCH (MT) PROTOCOL
M: Henrik Rydberg <rydberg@euromail.se>
......
......@@ -25,10 +25,6 @@ config INPUT
if INPUT
config INPUT_OF_MATRIX_KEYMAP
depends on USE_OF
bool
config INPUT_FF_MEMLESS
tristate "Support for memoryless force-feedback devices"
help
......@@ -68,6 +64,19 @@ config INPUT_SPARSEKMAP
To compile this driver as a module, choose M here: the
module will be called sparse-keymap.
config INPUT_MATRIXKMAP
tristate "Matrix keymap support library"
help
Say Y here if you are using a driver for an input
device that uses matrix keymap. This option is only
useful for out-of-tree drivers since in-tree drivers
select it automatically.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called matrix-keymap.
comment "Userland interfaces"
config INPUT_MOUSEDEV
......
......@@ -10,6 +10,7 @@ input-core-y := input.o input-compat.o input-mt.o ff-core.o
obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o
obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o
obj-$(CONFIG_INPUT_SPARSEKMAP) += sparse-keymap.o
obj-$(CONFIG_INPUT_MATRIXKMAP) += matrix-keymap.o
obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o
obj-$(CONFIG_INPUT_JOYDEV) += joydev.o
......@@ -24,4 +25,3 @@ obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
obj-$(CONFIG_INPUT_MISC) += misc/
obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o
obj-$(CONFIG_INPUT_OF_MATRIX_KEYMAP) += of_keymap.o
......@@ -180,7 +180,10 @@ static int evdev_grab(struct evdev *evdev, struct evdev_client *client)
static int evdev_ungrab(struct evdev *evdev, struct evdev_client *client)
{
if (evdev->grab != client)
struct evdev_client *grab = rcu_dereference_protected(evdev->grab,
lockdep_is_held(&evdev->mutex));
if (grab != client)
return -EINVAL;
rcu_assign_pointer(evdev->grab, NULL);
......@@ -259,8 +262,7 @@ static int evdev_release(struct inode *inode, struct file *file)
struct evdev *evdev = client->evdev;
mutex_lock(&evdev->mutex);
if (evdev->grab == client)
evdev_ungrab(evdev, client);
evdev_ungrab(evdev, client);
mutex_unlock(&evdev->mutex);
evdev_detach_client(evdev, client);
......@@ -343,7 +345,7 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer,
struct input_event event;
int retval = 0;
if (count < input_event_size())
if (count != 0 && count < input_event_size())
return -EINVAL;
retval = mutex_lock_interruptible(&evdev->mutex);
......@@ -355,7 +357,8 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer,
goto out;
}
do {
while (retval + input_event_size() <= count) {
if (input_event_from_user(buffer + retval, &event)) {
retval = -EFAULT;
goto out;
......@@ -364,7 +367,7 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer,
input_inject_event(&evdev->handle,
event.type, event.code, event.value);
} while (retval + input_event_size() <= count);
}
out:
mutex_unlock(&evdev->mutex);
......@@ -395,35 +398,49 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
struct input_event event;
int retval = 0;
size_t read = 0;
int error;
if (count < input_event_size())
if (count != 0 && count < input_event_size())
return -EINVAL;
if (!(file->f_flags & O_NONBLOCK)) {
retval = wait_event_interruptible(evdev->wait,
client->packet_head != client->tail ||
!evdev->exist);
if (retval)
return retval;
}
for (;;) {
if (!evdev->exist)
return -ENODEV;
if (!evdev->exist)
return -ENODEV;
if (client->packet_head == client->tail &&
(file->f_flags & O_NONBLOCK))
return -EAGAIN;
while (retval + input_event_size() <= count &&
evdev_fetch_next_event(client, &event)) {
/*
* count == 0 is special - no IO is done but we check
* for error conditions (see above).
*/
if (count == 0)
break;
if (input_event_to_user(buffer + retval, &event))
return -EFAULT;
while (read + input_event_size() <= count &&
evdev_fetch_next_event(client, &event)) {
retval += input_event_size();
}
if (input_event_to_user(buffer + read, &event))
return -EFAULT;
if (retval == 0 && (file->f_flags & O_NONBLOCK))
return -EAGAIN;
read += input_event_size();
}
return retval;
if (read)
break;
if (!(file->f_flags & O_NONBLOCK)) {
error = wait_event_interruptible(evdev->wait,
client->packet_head != client->tail ||
!evdev->exist);
if (error)
return error;
}
}
return read;
}
/* No kernel lock - fine */
......
......@@ -125,15 +125,4 @@ static struct pci_driver emu_driver = {
.remove = __devexit_p(emu_remove),
};
static int __init emu_init(void)
{
return pci_register_driver(&emu_driver);
}
static void __exit emu_exit(void)
{
pci_unregister_driver(&emu_driver);
}
module_init(emu_init);
module_exit(emu_exit);
module_pci_driver(emu_driver);
......@@ -144,6 +144,7 @@ static const struct pci_device_id fm801_gp_id_table[] = {
{ PCI_VENDOR_ID_FORTEMEDIA, PCI_DEVICE_ID_FM801_GP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, fm801_gp_id_table);
static struct pci_driver fm801_gp_driver = {
.name = "FM801_gameport",
......@@ -152,20 +153,7 @@ static struct pci_driver fm801_gp_driver = {
.remove = __devexit_p(fm801_gp_remove),
};
static int __init fm801_gp_init(void)
{
return pci_register_driver(&fm801_gp_driver);
}
static void __exit fm801_gp_exit(void)
{
pci_unregister_driver(&fm801_gp_driver);
}
module_init(fm801_gp_init);
module_exit(fm801_gp_exit);
MODULE_DEVICE_TABLE(pci, fm801_gp_id_table);
module_pci_driver(fm801_gp_driver);
MODULE_DESCRIPTION("FM801 gameport driver");
MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
......
......@@ -413,15 +413,4 @@ static struct gameport_driver a3d_drv = {
.disconnect = a3d_disconnect,
};
static int __init a3d_init(void)
{
return gameport_register_driver(&a3d_drv);
}
static void __exit a3d_exit(void)
{
gameport_unregister_driver(&a3d_drv);
}
module_init(a3d_init);
module_exit(a3d_exit);
module_gameport_driver(a3d_drv);
......@@ -557,10 +557,6 @@ static void adi_disconnect(struct gameport *gameport)
kfree(port);
}
/*
* The gameport device structure.
*/
static struct gameport_driver adi_drv = {
.driver = {
.name = "adi",
......@@ -570,15 +566,4 @@ static struct gameport_driver adi_drv = {
.disconnect = adi_disconnect,
};
static int __init adi_init(void)
{
return gameport_register_driver(&adi_drv);
}
static void __exit adi_exit(void)
{
gameport_unregister_driver(&adi_drv);
}
module_init(adi_init);
module_exit(adi_exit);
module_gameport_driver(adi_drv);
......@@ -261,15 +261,4 @@ static struct gameport_driver cobra_drv = {
.disconnect = cobra_disconnect,
};
static int __init cobra_init(void)
{
return gameport_register_driver(&cobra_drv);
}
static void __exit cobra_exit(void)
{
gameport_unregister_driver(&cobra_drv);
}
module_init(cobra_init);
module_exit(cobra_exit);
module_gameport_driver(cobra_drv);
......@@ -373,15 +373,4 @@ static struct gameport_driver gf2k_drv = {
.disconnect = gf2k_disconnect,
};
static int __init gf2k_init(void)
{
return gameport_register_driver(&gf2k_drv);
}
static void __exit gf2k_exit(void)
{
gameport_unregister_driver(&gf2k_drv);
}
module_init(gf2k_init);
module_exit(gf2k_exit);
module_gameport_driver(gf2k_drv);
......@@ -424,15 +424,4 @@ static struct gameport_driver grip_drv = {
.disconnect = grip_disconnect,
};
static int __init grip_init(void)
{
return gameport_register_driver(&grip_drv);
}
static void __exit grip_exit(void)
{
gameport_unregister_driver(&grip_drv);
}
module_init(grip_init);
module_exit(grip_exit);
module_gameport_driver(grip_drv);
......@@ -687,15 +687,4 @@ static struct gameport_driver grip_drv = {
.disconnect = grip_disconnect,
};
static int __init grip_init(void)
{
return gameport_register_driver(&grip_drv);
}
static void __exit grip_exit(void)
{
gameport_unregister_driver(&grip_drv);
}
module_init(grip_init);
module_exit(grip_exit);
module_gameport_driver(grip_drv);
......@@ -281,15 +281,4 @@ static struct gameport_driver guillemot_drv = {
.disconnect = guillemot_disconnect,
};
static int __init guillemot_init(void)
{
return gameport_register_driver(&guillemot_drv);
}
static void __exit guillemot_exit(void)
{
gameport_unregister_driver(&guillemot_drv);
}
module_init(guillemot_init);
module_exit(guillemot_exit);
module_gameport_driver(guillemot_drv);
......@@ -311,15 +311,4 @@ static struct gameport_driver interact_drv = {
.disconnect = interact_disconnect,
};
static int __init interact_init(void)
{
return gameport_register_driver(&interact_drv);
}
static void __exit interact_exit(void)
{
gameport_unregister_driver(&interact_drv);
}
module_init(interact_init);
module_exit(interact_exit);
module_gameport_driver(interact_drv);
......@@ -159,15 +159,4 @@ static struct gameport_driver joydump_drv = {
.disconnect = joydump_disconnect,
};
static int __init joydump_init(void)
{
return gameport_register_driver(&joydump_drv);
}
static void __exit joydump_exit(void)
{
gameport_unregister_driver(&joydump_drv);
}
module_init(joydump_init);
module_exit(joydump_exit);
module_gameport_driver(joydump_drv);
......@@ -222,19 +222,4 @@ static struct serio_driver magellan_drv = {
.disconnect = magellan_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
static int __init magellan_init(void)
{
return serio_register_driver(&magellan_drv);
}
static void __exit magellan_exit(void)
{
serio_unregister_driver(&magellan_drv);
}
module_init(magellan_init);
module_exit(magellan_exit);
module_serio_driver(magellan_drv);
......@@ -820,15 +820,4 @@ static struct gameport_driver sw_drv = {
.disconnect = sw_disconnect,
};
static int __init sw_init(void)
{
return gameport_register_driver(&sw_drv);
}
static void __exit sw_exit(void)
{
gameport_unregister_driver(&sw_drv);
}
module_init(sw_init);
module_exit(sw_exit);
module_gameport_driver(sw_drv);
......@@ -296,19 +296,4 @@ static struct serio_driver spaceball_drv = {
.disconnect = spaceball_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
static int __init spaceball_init(void)
{
return serio_register_driver(&spaceball_drv);
}
static void __exit spaceball_exit(void)
{
serio_unregister_driver(&spaceball_drv);
}
module_init(spaceball_init);
module_exit(spaceball_exit);
module_serio_driver(spaceball_drv);
......@@ -237,19 +237,4 @@ static struct serio_driver spaceorb_drv = {
.disconnect = spaceorb_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
static int __init spaceorb_init(void)
{
return serio_register_driver(&spaceorb_drv);
}
static void __exit spaceorb_exit(void)
{
serio_unregister_driver(&spaceorb_drv);
}
module_init(spaceorb_init);
module_exit(spaceorb_exit);
module_serio_driver(spaceorb_drv);
......@@ -208,19 +208,4 @@ static struct serio_driver stinger_drv = {
.disconnect = stinger_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
static int __init stinger_init(void)
{
return serio_register_driver(&stinger_drv);
}
static void __exit stinger_exit(void)
{
serio_unregister_driver(&stinger_drv);
}
module_init(stinger_init);
module_exit(stinger_exit);
module_serio_driver(stinger_drv);
......@@ -436,15 +436,4 @@ static struct gameport_driver tmdc_drv = {
.disconnect = tmdc_disconnect,
};
static int __init tmdc_init(void)
{
return gameport_register_driver(&tmdc_drv);
}
static void __exit tmdc_exit(void)
{
gameport_unregister_driver(&tmdc_drv);
}
module_init(tmdc_init);
module_exit(tmdc_exit);
module_gameport_driver(tmdc_drv);
......@@ -257,19 +257,4 @@ static struct serio_driver twidjoy_drv = {
.disconnect = twidjoy_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
static int __init twidjoy_init(void)
{
return serio_register_driver(&twidjoy_drv);
}
static void __exit twidjoy_exit(void)
{
serio_unregister_driver(&twidjoy_drv);
}
module_init(twidjoy_init);
module_exit(twidjoy_exit);
module_serio_driver(twidjoy_drv);
......@@ -217,19 +217,4 @@ static struct serio_driver warrior_drv = {
.disconnect = warrior_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
static int __init warrior_init(void)
{
return serio_register_driver(&warrior_drv);
}
static void __exit warrior_exit(void)
{
serio_unregister_driver(&warrior_drv);
}
module_init(warrior_init);
module_exit(warrior_exit);
module_serio_driver(warrior_drv);
......@@ -225,19 +225,4 @@ static struct serio_driver zhenhua_drv = {
.disconnect = zhenhua_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
static int __init zhenhua_init(void)
{
return serio_register_driver(&zhenhua_drv);
}
static void __exit zhenhua_exit(void)
{
serio_unregister_driver(&zhenhua_drv);
}
module_init(zhenhua_init);
module_exit(zhenhua_exit);
module_serio_driver(zhenhua_drv);
......@@ -166,6 +166,7 @@ config KEYBOARD_LKKBD
config KEYBOARD_EP93XX
tristate "EP93xx Matrix Keypad support"
depends on ARCH_EP93XX
select INPUT_MATRIXKMAP
help
Say Y here to enable the matrix keypad on the Cirrus EP93XX.
......@@ -224,6 +225,7 @@ config KEYBOARD_TCA6416
config KEYBOARD_TCA8418
tristate "TCA8418 Keypad Support"
depends on I2C
select INPUT_MATRIXKMAP
help
This driver implements basic keypad functionality
for keys connected through TCA8418 keypad decoder.
......@@ -240,6 +242,7 @@ config KEYBOARD_TCA8418
config KEYBOARD_MATRIX
tristate "GPIO driven matrix keypad support"
depends on GENERIC_GPIO
select INPUT_MATRIXKMAP
help
Enable support for GPIO driven matrix keypad.
......@@ -309,6 +312,17 @@ config KEYBOARD_LM8323
To compile this driver as a module, choose M here: the
module will be called lm8323.
config KEYBOARD_LM8333
tristate "LM8333 keypad chip"
depends on I2C
select INPUT_MATRIXKMAP
help
If you say yes here you get support for the National Semiconductor
LM8333 keypad controller.
To compile this driver as a module, choose M here: the
module will be called lm8333.
config KEYBOARD_LOCOMO
tristate "LoCoMo Keyboard Support"
depends on SHARP_LOCOMO
......@@ -366,6 +380,7 @@ config KEYBOARD_MPR121
config KEYBOARD_IMX
tristate "IMX keypad support"
depends on ARCH_MXC
select INPUT_MATRIXKMAP
help
Enable support for IMX keypad port.
......@@ -384,6 +399,7 @@ config KEYBOARD_NEWTON
config KEYBOARD_NOMADIK
tristate "ST-Ericsson Nomadik SKE keyboard"
depends on PLAT_NOMADIK
select INPUT_MATRIXKMAP
help
Say Y here if you want to use a keypad provided on the SKE controller
used on the Ux500 and Nomadik platforms
......@@ -394,7 +410,7 @@ config KEYBOARD_NOMADIK
config KEYBOARD_TEGRA
tristate "NVIDIA Tegra internal matrix keyboard controller support"
depends on ARCH_TEGRA
select INPUT_OF_MATRIX_KEYMAP if USE_OF
select INPUT_MATRIXKMAP
help
Say Y here if you want to use a matrix keyboard connected directly
to the internal keyboard controller on Tegra SoCs.
......@@ -432,6 +448,7 @@ config KEYBOARD_PXA930_ROTARY
config KEYBOARD_PMIC8XXX
tristate "Qualcomm PMIC8XXX keypad support"
depends on MFD_PM8XXX
select INPUT_MATRIXKMAP
help
Say Y here if you want to enable the driver for the PMIC8XXX
keypad provided as a reference design from Qualcomm. This is intended
......@@ -443,6 +460,7 @@ config KEYBOARD_PMIC8XXX
config KEYBOARD_SAMSUNG
tristate "Samsung keypad support"
depends on HAVE_CLK
select INPUT_MATRIXKMAP
help
Say Y here if you want to use the keypad on your Samsung mobile
device.
......@@ -485,6 +503,7 @@ config KEYBOARD_SH_KEYSC
config KEYBOARD_STMPE
tristate "STMPE keypad support"
depends on MFD_STMPE
select INPUT_MATRIXKMAP
help
Say Y here if you want to use the keypad controller on STMPE I/O
expanders.
......@@ -505,6 +524,7 @@ config KEYBOARD_DAVINCI
config KEYBOARD_OMAP
tristate "TI OMAP keypad support"
depends on (ARCH_OMAP1 || ARCH_OMAP2)
select INPUT_MATRIXKMAP
help
Say Y here if you want to use the OMAP keypad.
......@@ -512,9 +532,10 @@ config KEYBOARD_OMAP
module will be called omap-keypad.
config KEYBOARD_OMAP4
tristate "TI OMAP4 keypad support"
tristate "TI OMAP4+ keypad support"
select INPUT_MATRIXKMAP
help
Say Y here if you want to use the OMAP4 keypad.
Say Y here if you want to use the OMAP4+ keypad.
To compile this driver as a module, choose M here: the
module will be called omap4-keypad.
......@@ -522,6 +543,7 @@ config KEYBOARD_OMAP4
config KEYBOARD_SPEAR
tristate "ST SPEAR keyboard support"
depends on PLAT_SPEAR
select INPUT_MATRIXKMAP
help
Say Y here if you want to use the SPEAR keyboard.
......@@ -531,6 +553,7 @@ config KEYBOARD_SPEAR
config KEYBOARD_TC3589X
tristate "TC3589X Keypad support"
depends on MFD_TC3589X
select INPUT_MATRIXKMAP
help
Say Y here if you want to use the keypad controller on
TC35892/3 I/O expander.
......@@ -541,6 +564,7 @@ config KEYBOARD_TC3589X
config KEYBOARD_TNETV107X
tristate "TI TNETV107X keypad support"
depends on ARCH_DAVINCI_TNETV107X
select INPUT_MATRIXKMAP
help
Say Y here if you want to use the TNETV107X keypad.
......@@ -550,6 +574,7 @@ config KEYBOARD_TNETV107X
config KEYBOARD_TWL4030
tristate "TI TWL4030/TWL5030/TPS659x0 keypad support"
depends on TWL4030_CORE
select INPUT_MATRIXKMAP
help
Say Y here if your board use the keypad controller on
TWL4030 family chips. It's safe to say enable this
......@@ -573,6 +598,7 @@ config KEYBOARD_XTKBD
config KEYBOARD_W90P910
tristate "W90P910 Matrix Keypad support"
depends on ARCH_W90X900
select INPUT_MATRIXKMAP
help
Say Y here to enable the matrix keypad on evaluation board
based on W90P910.
......
......@@ -24,6 +24,7 @@ obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o
obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o
obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o
obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o
obj-$(CONFIG_KEYBOARD_LM8333) += lm8333.o
obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o
obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o
......
......@@ -197,6 +197,7 @@ static int __devinit adp5588_gpio_add(struct adp5588_kpad *kpad)
kpad->gc.base = gpio_data->gpio_start;
kpad->gc.label = kpad->client->name;
kpad->gc.owner = THIS_MODULE;
kpad->gc.names = gpio_data->names;
mutex_init(&kpad->gpio_lock);
......
......@@ -433,7 +433,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
if (printk_ratelimit())
dev_warn(&serio->dev,
"Spurious %s on %s. "
"Some program might be trying access hardware directly.\n",
"Some program might be trying to access hardware directly.\n",
data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
goto out;
case ATKBD_RET_ERR:
......
......@@ -182,16 +182,10 @@ static void ep93xx_keypad_close(struct input_dev *pdev)
}
#ifdef CONFIG_PM
/*
* NOTE: I don't know if this is correct, or will work on the ep93xx.
*
* None of the existing ep93xx drivers have power management support.
* But, this is basically what the pxa27x_keypad driver does.
*/
static int ep93xx_keypad_suspend(struct platform_device *pdev,
pm_message_t state)
#ifdef CONFIG_PM_SLEEP
static int ep93xx_keypad_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
struct input_dev *input_dev = keypad->input_dev;
......@@ -210,8 +204,9 @@ static int ep93xx_keypad_suspend(struct platform_device *pdev,
return 0;
}
static int ep93xx_keypad_resume(struct platform_device *pdev)
static int ep93xx_keypad_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
struct input_dev *input_dev = keypad->input_dev;
......@@ -232,10 +227,10 @@ static int ep93xx_keypad_resume(struct platform_device *pdev)
return 0;
}
#else /* !CONFIG_PM */
#define ep93xx_keypad_suspend NULL
#define ep93xx_keypad_resume NULL
#endif /* !CONFIG_PM */
#endif
static SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops,
ep93xx_keypad_suspend, ep93xx_keypad_resume);
static int __devinit ep93xx_keypad_probe(struct platform_device *pdev)
{
......@@ -308,19 +303,16 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev)
input_dev->open = ep93xx_keypad_open;
input_dev->close = ep93xx_keypad_close;
input_dev->dev.parent = &pdev->dev;
input_dev->keycode = keypad->keycodes;
input_dev->keycodesize = sizeof(keypad->keycodes[0]);
input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes);
input_set_drvdata(input_dev, keypad);
err = matrix_keypad_build_keymap(keymap_data, NULL,
EP93XX_MATRIX_ROWS, EP93XX_MATRIX_COLS,
keypad->keycodes, input_dev);
if (err)
goto failed_free_dev;
input_dev->evbit[0] = BIT_MASK(EV_KEY);
if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT)
input_dev->evbit[0] |= BIT_MASK(EV_REP);
matrix_keypad_build_keymap(keymap_data, 3,
input_dev->keycode, input_dev->keybit);
platform_set_drvdata(pdev, keypad);
__set_bit(EV_REP, input_dev->evbit);
input_set_drvdata(input_dev, keypad);
err = request_irq(keypad->irq, ep93xx_keypad_irq_handler,
0, pdev->name, keypad);
......@@ -331,6 +323,7 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev)
if (err)
goto failed_free_irq;
platform_set_drvdata(pdev, keypad);
device_init_wakeup(&pdev->dev, 1);
return 0;
......@@ -384,11 +377,10 @@ static struct platform_driver ep93xx_keypad_driver = {
.driver = {
.name = "ep93xx-keypad",
.owner = THIS_MODULE,
.pm = &ep93xx_keypad_pm_ops,
},
.probe = ep93xx_keypad_probe,
.remove = __devexit_p(ep93xx_keypad_remove),
.suspend = ep93xx_keypad_suspend,
.resume = ep93xx_keypad_resume,
};
module_platform_driver(ep93xx_keypad_driver);
......
......@@ -583,15 +583,4 @@ static struct serio_driver hil_serio_drv = {
.interrupt = hil_dev_interrupt
};
static int __init hil_dev_init(void)
{
return serio_register_driver(&hil_serio_drv);
}
static void __exit hil_dev_exit(void)
{
serio_unregister_driver(&hil_serio_drv);
}
module_init(hil_dev_init);
module_exit(hil_dev_exit);
module_serio_driver(hil_serio_drv);
......@@ -481,7 +481,7 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev)
}
if (keypad->rows_en_mask > ((1 << MAX_MATRIX_KEY_ROWS) - 1) ||
keypad->cols_en_mask > ((1 << MAX_MATRIX_KEY_COLS) - 1)) {
keypad->cols_en_mask > ((1 << MAX_MATRIX_KEY_COLS) - 1)) {
dev_err(&pdev->dev,
"invalid key data (too many rows or colums)\n");
error = -EINVAL;
......@@ -496,14 +496,17 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev)
input_dev->dev.parent = &pdev->dev;
input_dev->open = imx_keypad_open;
input_dev->close = imx_keypad_close;
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
input_dev->keycode = keypad->keycodes;
input_dev->keycodesize = sizeof(keypad->keycodes[0]);
input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes);
matrix_keypad_build_keymap(keymap_data, MATRIX_ROW_SHIFT,
keypad->keycodes, input_dev->keybit);
error = matrix_keypad_build_keymap(keymap_data, NULL,
MAX_MATRIX_KEY_ROWS,
MAX_MATRIX_KEY_COLS,
keypad->keycodes, input_dev);
if (error) {
dev_err(&pdev->dev, "failed to build keymap\n");
goto failed_clock_put;
}
__set_bit(EV_REP, input_dev->evbit);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
input_set_drvdata(input_dev, keypad);
......
......@@ -731,19 +731,4 @@ static struct serio_driver lkkbd_drv = {
.interrupt = lkkbd_interrupt,
};
/*
* The functions for insering/removing us as a module.
*/
static int __init lkkbd_init(void)
{
return serio_register_driver(&lkkbd_drv);
}
static void __exit lkkbd_exit(void)
{
serio_unregister_driver(&lkkbd_drv);
}
module_init(lkkbd_init);
module_exit(lkkbd_exit);
module_serio_driver(lkkbd_drv);
/*
* LM8333 keypad driver
* Copyright (C) 2012 Wolfram Sang, Pengutronix <w.sang@pengutronix.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/irq.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/input/matrix_keypad.h>
#include <linux/input/lm8333.h>
#define LM8333_FIFO_READ 0x20
#define LM8333_DEBOUNCE 0x22
#define LM8333_READ_INT 0xD0
#define LM8333_ACTIVE 0xE4
#define LM8333_READ_ERROR 0xF0
#define LM8333_KEYPAD_IRQ (1 << 0)
#define LM8333_ERROR_IRQ (1 << 3)
#define LM8333_ERROR_KEYOVR 0x04
#define LM8333_ERROR_FIFOOVR 0x40
#define LM8333_FIFO_TRANSFER_SIZE 16
#define LM8333_NUM_ROWS 8
#define LM8333_NUM_COLS 16
#define LM8333_ROW_SHIFT 4
struct lm8333 {
struct i2c_client *client;
struct input_dev *input;
unsigned short keycodes[LM8333_NUM_ROWS << LM8333_ROW_SHIFT];
};
/* The accessors try twice because the first access may be needed for wakeup */
#define LM8333_READ_RETRIES 2
int lm8333_read8(struct lm8333 *lm8333, u8 cmd)
{
int retries = 0, ret;
do {
ret = i2c_smbus_read_byte_data(lm8333->client, cmd);
} while (ret < 0 && retries++ < LM8333_READ_RETRIES);
return ret;
}
int lm8333_write8(struct lm8333 *lm8333, u8 cmd, u8 val)
{
int retries = 0, ret;
do {
ret = i2c_smbus_write_byte_data(lm8333->client, cmd, val);
} while (ret < 0 && retries++ < LM8333_READ_RETRIES);
return ret;
}
int lm8333_read_block(struct lm8333 *lm8333, u8 cmd, u8 len, u8 *buf)
{
int retries = 0, ret;
do {
ret = i2c_smbus_read_i2c_block_data(lm8333->client,
cmd, len, buf);
} while (ret < 0 && retries++ < LM8333_READ_RETRIES);
return ret;
}
static void lm8333_key_handler(struct lm8333 *lm8333)
{
struct input_dev *input = lm8333->input;
u8 keys[LM8333_FIFO_TRANSFER_SIZE];
u8 code, pressed;
int i, ret;
ret = lm8333_read_block(lm8333, LM8333_FIFO_READ,
LM8333_FIFO_TRANSFER_SIZE, keys);
if (ret != LM8333_FIFO_TRANSFER_SIZE) {
dev_err(&lm8333->client->dev,
"Error %d while reading FIFO\n", ret);
return;
}
for (i = 0; keys[i] && i < LM8333_FIFO_TRANSFER_SIZE; i++) {
pressed = keys[i] & 0x80;
code = keys[i] & 0x7f;
input_event(input, EV_MSC, MSC_SCAN, code);
input_report_key(input, lm8333->keycodes[code], pressed);
}
input_sync(input);
}
static irqreturn_t lm8333_irq_thread(int irq, void *data)
{
struct lm8333 *lm8333 = data;
u8 status = lm8333_read8(lm8333, LM8333_READ_INT);
if (!status)
return IRQ_NONE;
if (status & LM8333_ERROR_IRQ) {
u8 err = lm8333_read8(lm8333, LM8333_READ_ERROR);
if (err & (LM8333_ERROR_KEYOVR | LM8333_ERROR_FIFOOVR)) {
u8 dummy[LM8333_FIFO_TRANSFER_SIZE];
lm8333_read_block(lm8333, LM8333_FIFO_READ,
LM8333_FIFO_TRANSFER_SIZE, dummy);
}
dev_err(&lm8333->client->dev, "Got error %02x\n", err);
}
if (status & LM8333_KEYPAD_IRQ)
lm8333_key_handler(lm8333);
return IRQ_HANDLED;
}
static int __devinit lm8333_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
const struct lm8333_platform_data *pdata = client->dev.platform_data;
struct lm8333 *lm8333;
struct input_dev *input;
int err, active_time;
if (!pdata)
return -EINVAL;
active_time = pdata->active_time ?: 500;
if (active_time / 3 <= pdata->debounce_time / 3) {
dev_err(&client->dev, "Active time not big enough!\n");
return -EINVAL;
}
lm8333 = kzalloc(sizeof(*lm8333), GFP_KERNEL);
input = input_allocate_device();
if (!lm8333 || !input) {
err = -ENOMEM;
goto free_mem;
}
lm8333->client = client;
lm8333->input = input;
input->name = client->name;
input->dev.parent = &client->dev;
input->id.bustype = BUS_I2C;
input_set_capability(input, EV_MSC, MSC_SCAN);
err = matrix_keypad_build_keymap(pdata->matrix_data, NULL,
LM8333_NUM_ROWS, LM8333_NUM_COLS,
lm8333->keycodes, input);
if (err)
goto free_mem;
if (pdata->debounce_time) {
err = lm8333_write8(lm8333, LM8333_DEBOUNCE,
pdata->debounce_time / 3);
if (err)
dev_warn(&client->dev, "Unable to set debounce time\n");
}
if (pdata->active_time) {
err = lm8333_write8(lm8333, LM8333_ACTIVE,
pdata->active_time / 3);
if (err)
dev_warn(&client->dev, "Unable to set active time\n");
}
err = request_threaded_irq(client->irq, NULL, lm8333_irq_thread,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"lm8333", lm8333);
if (err)
goto free_mem;
err = input_register_device(input);
if (err)
goto free_irq;
i2c_set_clientdata(client, lm8333);
return 0;
free_irq:
free_irq(client->irq, lm8333);
free_mem:
input_free_device(input);
kfree(lm8333);
return err;
}
static int __devexit lm8333_remove(struct i2c_client *client)
{
struct lm8333 *lm8333 = i2c_get_clientdata(client);
free_irq(client->irq, lm8333);
input_unregister_device(lm8333->input);
kfree(lm8333);
return 0;
}
static const struct i2c_device_id lm8333_id[] = {
{ "lm8333", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm8333_id);
static struct i2c_driver lm8333_driver = {
.driver = {
.name = "lm8333",
.owner = THIS_MODULE,
},
.probe = lm8333_probe,
.remove = __devexit_p(lm8333_remove),
.id_table = lm8333_id,
};
module_i2c_driver(lm8333_driver);
MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
MODULE_DESCRIPTION("LM8333 keyboard driver");
MODULE_LICENSE("GPL v2");
......@@ -27,7 +27,6 @@
struct matrix_keypad {
const struct matrix_keypad_platform_data *pdata;
struct input_dev *input_dev;
unsigned short *keycodes;
unsigned int row_shift;
DECLARE_BITMAP(disabled_gpios, MATRIX_MAX_ROWS);
......@@ -38,6 +37,8 @@ struct matrix_keypad {
bool scan_pending;
bool stopped;
bool gpio_all_disabled;
unsigned short keycodes[];
};
/*
......@@ -224,7 +225,7 @@ static void matrix_keypad_stop(struct input_dev *dev)
disable_row_irqs(keypad);
}
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static void matrix_keypad_enable_wakeup(struct matrix_keypad *keypad)
{
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
......@@ -293,16 +294,16 @@ static int matrix_keypad_resume(struct device *dev)
return 0;
}
static const SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops,
matrix_keypad_suspend, matrix_keypad_resume);
#endif
static int __devinit init_matrix_gpio(struct platform_device *pdev,
struct matrix_keypad *keypad)
static SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops,
matrix_keypad_suspend, matrix_keypad_resume);
static int __devinit matrix_keypad_init_gpio(struct platform_device *pdev,
struct matrix_keypad *keypad)
{
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
int i, err = -EINVAL;
int i, err;
/* initialized strobe lines as outputs, activated */
for (i = 0; i < pdata->num_col_gpios; i++) {
......@@ -348,8 +349,7 @@ static int __devinit init_matrix_gpio(struct platform_device *pdev,
"matrix-keypad", keypad);
if (err) {
dev_err(&pdev->dev,
"Unable to acquire interrupt "
"for GPIO line %i\n",
"Unable to acquire interrupt for GPIO line %i\n",
pdata->row_gpios[i]);
goto err_free_irqs;
}
......@@ -375,14 +375,33 @@ static int __devinit init_matrix_gpio(struct platform_device *pdev,
return err;
}
static void matrix_keypad_free_gpio(struct matrix_keypad *keypad)
{
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
int i;
if (pdata->clustered_irq > 0) {
free_irq(pdata->clustered_irq, keypad);
} else {
for (i = 0; i < pdata->num_row_gpios; i++)
free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
}
for (i = 0; i < pdata->num_row_gpios; i++)
gpio_free(pdata->row_gpios[i]);
for (i = 0; i < pdata->num_col_gpios; i++)
gpio_free(pdata->col_gpios[i]);
}
static int __devinit matrix_keypad_probe(struct platform_device *pdev)
{
const struct matrix_keypad_platform_data *pdata;
const struct matrix_keymap_data *keymap_data;
struct matrix_keypad *keypad;
struct input_dev *input_dev;
unsigned short *keycodes;
unsigned int row_shift;
size_t keymap_size;
int err;
pdata = pdev->dev.platform_data;
......@@ -398,20 +417,18 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev)
}
row_shift = get_count_order(pdata->num_col_gpios);
keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL);
keycodes = kzalloc((pdata->num_row_gpios << row_shift) *
sizeof(*keycodes),
GFP_KERNEL);
keymap_size = (pdata->num_row_gpios << row_shift) *
sizeof(keypad->keycodes[0]);
keypad = kzalloc(sizeof(struct matrix_keypad) + keymap_size,
GFP_KERNEL);
input_dev = input_allocate_device();
if (!keypad || !keycodes || !input_dev) {
if (!keypad || !input_dev) {
err = -ENOMEM;
goto err_free_mem;
}
keypad->input_dev = input_dev;
keypad->pdata = pdata;
keypad->keycodes = keycodes;
keypad->row_shift = row_shift;
keypad->stopped = true;
INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
......@@ -420,38 +437,38 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev)
input_dev->name = pdev->name;
input_dev->id.bustype = BUS_HOST;
input_dev->dev.parent = &pdev->dev;
input_dev->evbit[0] = BIT_MASK(EV_KEY);
if (!pdata->no_autorepeat)
input_dev->evbit[0] |= BIT_MASK(EV_REP);
input_dev->open = matrix_keypad_start;
input_dev->close = matrix_keypad_stop;
input_dev->keycode = keycodes;
input_dev->keycodesize = sizeof(*keycodes);
input_dev->keycodemax = pdata->num_row_gpios << row_shift;
matrix_keypad_build_keymap(keymap_data, row_shift,
input_dev->keycode, input_dev->keybit);
err = matrix_keypad_build_keymap(keymap_data, NULL,
pdata->num_row_gpios,
pdata->num_col_gpios,
keypad->keycodes, input_dev);
if (err)
goto err_free_mem;
if (!pdata->no_autorepeat)
__set_bit(EV_REP, input_dev->evbit);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
input_set_drvdata(input_dev, keypad);
err = init_matrix_gpio(pdev, keypad);
err = matrix_keypad_init_gpio(pdev, keypad);
if (err)
goto err_free_mem;
err = input_register_device(keypad->input_dev);
if (err)
goto err_free_mem;
goto err_free_gpio;
device_init_wakeup(&pdev->dev, pdata->wakeup);
platform_set_drvdata(pdev, keypad);
return 0;
err_free_gpio:
matrix_keypad_free_gpio(keypad);
err_free_mem:
input_free_device(input_dev);
kfree(keycodes);
kfree(keypad);
return err;
}
......@@ -459,29 +476,15 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev)
static int __devexit matrix_keypad_remove(struct platform_device *pdev)
{
struct matrix_keypad *keypad = platform_get_drvdata(pdev);
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
int i;
device_init_wakeup(&pdev->dev, 0);
if (pdata->clustered_irq > 0) {
free_irq(pdata->clustered_irq, keypad);
} else {
for (i = 0; i < pdata->num_row_gpios; i++)
free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
}
for (i = 0; i < pdata->num_row_gpios; i++)
gpio_free(pdata->row_gpios[i]);
for (i = 0; i < pdata->num_col_gpios; i++)
gpio_free(pdata->col_gpios[i]);
matrix_keypad_free_gpio(keypad);
input_unregister_device(keypad->input_dev);
platform_set_drvdata(pdev, NULL);
kfree(keypad->keycodes);
kfree(keypad);
platform_set_drvdata(pdev, NULL);
return 0;
}
......@@ -491,9 +494,7 @@ static struct platform_driver matrix_keypad_driver = {
.driver = {
.name = "matrix-keypad",
.owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &matrix_keypad_pm_ops,
#endif
},
};
module_platform_driver(matrix_keypad_driver);
......
......@@ -166,15 +166,4 @@ static struct serio_driver nkbd_drv = {
.disconnect = nkbd_disconnect,
};
static int __init nkbd_init(void)
{
return serio_register_driver(&nkbd_drv);
}
static void __exit nkbd_exit(void)
{
serio_unregister_driver(&nkbd_drv);
}
module_init(nkbd_init);
module_exit(nkbd_exit);
module_serio_driver(nkbd_drv);
......@@ -39,7 +39,8 @@
#define SKE_KPRISA (0x1 << 2)
#define SKE_KEYPAD_ROW_SHIFT 3
#define SKE_KPD_KEYMAP_SIZE (8 * 8)
#define SKE_KPD_NUM_ROWS 8
#define SKE_KPD_NUM_COLS 8
/* keypad auto scan registers */
#define SKE_ASR0 0x20
......@@ -63,7 +64,7 @@ struct ske_keypad {
void __iomem *reg_base;
struct input_dev *input;
const struct ske_keypad_platform_data *board;
unsigned short keymap[SKE_KPD_KEYMAP_SIZE];
unsigned short keymap[SKE_KPD_NUM_ROWS * SKE_KPD_NUM_COLS];
struct clk *clk;
spinlock_t ske_keypad_lock;
};
......@@ -261,19 +262,18 @@ static int __init ske_keypad_probe(struct platform_device *pdev)
input->name = "ux500-ske-keypad";
input->dev.parent = &pdev->dev;
input->keycode = keypad->keymap;
input->keycodesize = sizeof(keypad->keymap[0]);
input->keycodemax = ARRAY_SIZE(keypad->keymap);
error = matrix_keypad_build_keymap(plat->keymap_data, NULL,
SKE_KPD_NUM_ROWS, SKE_KPD_NUM_COLS,
keypad->keymap, input);
if (error) {
dev_err(&pdev->dev, "Failed to build keymap\n");
goto err_iounmap;
}
input_set_capability(input, EV_MSC, MSC_SCAN);
__set_bit(EV_KEY, input->evbit);
if (!plat->no_autorepeat)
__set_bit(EV_REP, input->evbit);
matrix_keypad_build_keymap(plat->keymap_data, SKE_KEYPAD_ROW_SHIFT,
input->keycode, input->keybit);
clk_enable(keypad->clk);
/* go through board initialization helpers */
......
......@@ -61,6 +61,7 @@ struct omap_kp {
unsigned int cols;
unsigned long delay;
unsigned int debounce;
unsigned short keymap[];
};
static DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
......@@ -316,13 +317,6 @@ static int __devinit omap_kp_probe(struct platform_device *pdev)
if (!cpu_is_omap24xx())
omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
input_dev->keycode = &omap_kp[1];
input_dev->keycodesize = sizeof(unsigned short);
input_dev->keycodemax = keycodemax;
if (pdata->rep)
__set_bit(EV_REP, input_dev->evbit);
if (pdata->delay)
omap_kp->delay = pdata->delay;
......@@ -371,9 +365,6 @@ static int __devinit omap_kp_probe(struct platform_device *pdev)
goto err2;
/* setup input device */
__set_bit(EV_KEY, input_dev->evbit);
matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
input_dev->keycode, input_dev->keybit);
input_dev->name = "omap-keypad";
input_dev->phys = "omap-keypad/input0";
input_dev->dev.parent = &pdev->dev;
......@@ -383,6 +374,15 @@ static int __devinit omap_kp_probe(struct platform_device *pdev)
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
if (pdata->rep)
__set_bit(EV_REP, input_dev->evbit);
ret = matrix_keypad_build_keymap(pdata->keymap_data, NULL,
pdata->rows, pdata->cols,
omap_kp->keymap, input_dev);
if (ret < 0)
goto err3;
ret = input_register_device(omap_kp->input);
if (ret < 0) {
printk(KERN_ERR "Unable to register omap-keypad input device\n");
......
......@@ -68,19 +68,52 @@
#define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
enum {
KBD_REVISION_OMAP4 = 0,
KBD_REVISION_OMAP5,
};
struct omap4_keypad {
struct input_dev *input;
void __iomem *base;
int irq;
unsigned int irq;
unsigned int rows;
unsigned int cols;
u32 reg_offset;
u32 irqreg_offset;
unsigned int row_shift;
unsigned char key_state[8];
unsigned short keymap[];
};
static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
{
return __raw_readl(keypad_data->base +
keypad_data->reg_offset + offset);
}
static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
{
__raw_writel(value,
keypad_data->base + keypad_data->reg_offset + offset);
}
static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
{
return __raw_readl(keypad_data->base +
keypad_data->irqreg_offset + offset);
}
static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
u32 offset, u32 value)
{
__raw_writel(value,
keypad_data->base + keypad_data->irqreg_offset + offset);
}
/* Interrupt handler */
static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
{
......@@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
u32 *new_state = (u32 *) key_state;
/* Disable interrupts */
__raw_writel(OMAP4_VAL_IRQDISABLE,
keypad_data->base + OMAP4_KBD_IRQENABLE);
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
OMAP4_VAL_IRQDISABLE);
*new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
*(new_state + 1) = __raw_readl(keypad_data->base
+ OMAP4_KBD_FULLCODE63_32);
*new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
*(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
for (row = 0; row < keypad_data->rows; row++) {
changed = key_state[row] ^ keypad_data->key_state[row];
......@@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
sizeof(keypad_data->key_state));
/* clear pending interrupts */
__raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
keypad_data->base + OMAP4_KBD_IRQSTATUS);
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
/* enable interrupts */
__raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
keypad_data->base + OMAP4_KBD_IRQENABLE);
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
OMAP4_DEF_IRQENABLE_EVENTEN |
OMAP4_DEF_IRQENABLE_LONGKEY);
return IRQ_HANDLED;
}
......@@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
disable_irq(keypad_data->irq);
__raw_writel(OMAP4_VAL_FUNCTIONALCFG,
keypad_data->base + OMAP4_KBD_CTRL);
__raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
__raw_writel(OMAP4_VAL_IRQDISABLE,
keypad_data->base + OMAP4_KBD_IRQSTATUS);
__raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
keypad_data->base + OMAP4_KBD_IRQENABLE);
__raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
kbd_writel(keypad_data, OMAP4_KBD_CTRL,
OMAP4_VAL_FUNCTIONALCFG);
kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
OMAP4_VAL_DEBOUNCINGTIME);
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
OMAP4_VAL_IRQDISABLE);
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
OMAP4_DEF_IRQENABLE_EVENTEN |
OMAP4_DEF_IRQENABLE_LONGKEY);
kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
enable_irq(keypad_data->irq);
......@@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
disable_irq(keypad_data->irq);
/* Disable interrupts */
__raw_writel(OMAP4_VAL_IRQDISABLE,
keypad_data->base + OMAP4_KBD_IRQENABLE);
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
OMAP4_VAL_IRQDISABLE);
/* clear pending interrupts */
__raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
keypad_data->base + OMAP4_KBD_IRQSTATUS);
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
enable_irq(keypad_data->irq);
......@@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
struct resource *res;
resource_size_t size;
unsigned int row_shift, max_keys;
int rev;
int irq;
int error;
......@@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
keypad_data->rows = pdata->rows;
keypad_data->cols = pdata->cols;
/*
* Enable clocks for the keypad module so that we can read
* revision register.
*/
pm_runtime_enable(&pdev->dev);
error = pm_runtime_get_sync(&pdev->dev);
if (error) {
dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
goto err_unmap;
}
rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
rev &= 0x03 << 30;
rev >>= 30;
switch (rev) {
case KBD_REVISION_OMAP4:
keypad_data->reg_offset = 0x00;
keypad_data->irqreg_offset = 0x00;
break;
case KBD_REVISION_OMAP5:
keypad_data->reg_offset = 0x10;
keypad_data->irqreg_offset = 0x0c;
break;
default:
dev_err(&pdev->dev,
"Keypad reports unsupported revision %d", rev);
error = -EINVAL;
goto err_pm_put_sync;
}
/* input device allocation */
keypad_data->input = input_dev = input_allocate_device();
if (!input_dev) {
error = -ENOMEM;
goto err_unmap;
goto err_pm_put_sync;
}
input_dev->name = pdev->name;
......@@ -258,20 +322,19 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
input_dev->open = omap4_keypad_open;
input_dev->close = omap4_keypad_close;
input_dev->keycode = keypad_data->keymap;
input_dev->keycodesize = sizeof(keypad_data->keymap[0]);
input_dev->keycodemax = max_keys;
error = matrix_keypad_build_keymap(pdata->keymap_data, NULL,
pdata->rows, pdata->cols,
keypad_data->keymap, input_dev);
if (error) {
dev_err(&pdev->dev, "failed to build keymap\n");
goto err_free_input;
}
__set_bit(EV_KEY, input_dev->evbit);
__set_bit(EV_REP, input_dev->evbit);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
input_set_drvdata(input_dev, keypad_data);
matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
input_dev->keycode, input_dev->keybit);
error = request_irq(keypad_data->irq, omap4_keypad_interrupt,
IRQF_TRIGGER_RISING,
"omap4-keypad", keypad_data);
......@@ -280,7 +343,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
goto err_free_input;
}
pm_runtime_enable(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
error = input_register_device(keypad_data->input);
if (error < 0) {
......@@ -296,6 +359,8 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
free_irq(keypad_data->irq, keypad_data);
err_free_input:
input_free_device(input_dev);
err_pm_put_sync:
pm_runtime_put_sync(&pdev->dev);
err_unmap:
iounmap(keypad_data->base);
err_release_mem:
......
......@@ -626,21 +626,21 @@ static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev)
kp->input->id.product = 0x0001;
kp->input->id.vendor = 0x0001;
kp->input->evbit[0] = BIT_MASK(EV_KEY);
if (pdata->rep)
__set_bit(EV_REP, kp->input->evbit);
kp->input->keycode = kp->keycodes;
kp->input->keycodemax = PM8XXX_MATRIX_MAX_SIZE;
kp->input->keycodesize = sizeof(kp->keycodes);
kp->input->open = pmic8xxx_kp_open;
kp->input->close = pmic8xxx_kp_close;
matrix_keypad_build_keymap(keymap_data, PM8XXX_ROW_SHIFT,
kp->input->keycode, kp->input->keybit);
rc = matrix_keypad_build_keymap(keymap_data, NULL,
PM8XXX_MAX_ROWS, PM8XXX_MAX_COLS,
kp->keycodes, kp->input);
if (rc) {
dev_err(&pdev->dev, "failed to build keymap\n");
goto err_get_irq;
}
if (pdata->rep)
__set_bit(EV_REP, kp->input->evbit);
input_set_capability(kp->input, EV_MSC, MSC_SCAN);
input_set_drvdata(kp->input, kp);
/* initialize keypad state */
......
......@@ -454,23 +454,23 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev)
input_dev->name = pdev->name;
input_dev->id.bustype = BUS_HOST;
input_dev->dev.parent = &pdev->dev;
input_set_drvdata(input_dev, keypad);
input_dev->open = samsung_keypad_open;
input_dev->close = samsung_keypad_close;
input_dev->evbit[0] = BIT_MASK(EV_KEY);
if (!pdata->no_autorepeat)
input_dev->evbit[0] |= BIT_MASK(EV_REP);
error = matrix_keypad_build_keymap(keymap_data, NULL,
pdata->rows, pdata->cols,
keypad->keycodes, input_dev);
if (error) {
dev_err(&pdev->dev, "failed to build keymap\n");
goto err_put_clk;
}
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
if (!pdata->no_autorepeat)
__set_bit(EV_REP, input_dev->evbit);
input_dev->keycode = keypad->keycodes;
input_dev->keycodesize = sizeof(keypad->keycodes[0]);
input_dev->keycodemax = pdata->rows << row_shift;
matrix_keypad_build_keymap(keymap_data, row_shift,
input_dev->keycode, input_dev->keybit);
input_set_drvdata(input_dev, keypad);
keypad->irq = platform_get_irq(pdev, 0);
if (keypad->irq < 0) {
......
......@@ -19,6 +19,7 @@
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_wakeup.h>
#include <linux/slab.h>
......@@ -49,7 +50,9 @@
#define KEY_VALUE 0x00FFFFFF
#define ROW_MASK 0xF0
#define COLUMN_MASK 0x0F
#define ROW_SHIFT 4
#define NUM_ROWS 16
#define NUM_COLS 16
#define KEY_MATRIX_SHIFT 6
struct spear_kbd {
......@@ -60,7 +63,8 @@ struct spear_kbd {
unsigned int irq;
unsigned int mode;
unsigned short last_key;
unsigned short keycodes[256];
unsigned short keycodes[NUM_ROWS * NUM_COLS];
bool rep;
};
static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id)
......@@ -136,27 +140,49 @@ static void spear_kbd_close(struct input_dev *dev)
kbd->last_key = KEY_RESERVED;
}
static int __devinit spear_kbd_probe(struct platform_device *pdev)
#ifdef CONFIG_OF
static int __devinit spear_kbd_parse_dt(struct platform_device *pdev,
struct spear_kbd *kbd)
{
const struct kbd_platform_data *pdata = pdev->dev.platform_data;
const struct matrix_keymap_data *keymap;
struct spear_kbd *kbd;
struct input_dev *input_dev;
struct resource *res;
int irq;
struct device_node *np = pdev->dev.of_node;
int error;
u32 val;
if (!pdata) {
dev_err(&pdev->dev, "Invalid platform data\n");
if (!np) {
dev_err(&pdev->dev, "Missing DT data\n");
return -EINVAL;
}
keymap = pdata->keymap;
if (!keymap) {
dev_err(&pdev->dev, "no keymap defined\n");
return -EINVAL;
if (of_property_read_bool(np, "autorepeat"))
kbd->rep = true;
error = of_property_read_u32(np, "st,mode", &val);
if (error) {
dev_err(&pdev->dev, "DT: Invalid or missing mode\n");
return error;
}
kbd->mode = val;
return 0;
}
#else
static inline int spear_kbd_parse_dt(struct platform_device *pdev,
struct spear_kbd *kbd)
{
return -ENOSYS;
}
#endif
static int __devinit spear_kbd_probe(struct platform_device *pdev)
{
struct kbd_platform_data *pdata = dev_get_platdata(&pdev->dev);
const struct matrix_keymap_data *keymap = pdata ? pdata->keymap : NULL;
struct spear_kbd *kbd;
struct input_dev *input_dev;
struct resource *res;
int irq;
int error;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "no keyboard resource defined\n");
......@@ -179,7 +205,15 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev)
kbd->input = input_dev;
kbd->irq = irq;
kbd->mode = pdata->mode;
if (!pdata) {
error = spear_kbd_parse_dt(pdev, kbd);
if (error)
goto err_free_mem;
} else {
kbd->mode = pdata->mode;
kbd->rep = pdata->rep;
}
kbd->res = request_mem_region(res->start, resource_size(res),
pdev->name);
......@@ -212,18 +246,17 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev)
input_dev->open = spear_kbd_open;
input_dev->close = spear_kbd_close;
__set_bit(EV_KEY, input_dev->evbit);
if (pdata->rep)
error = matrix_keypad_build_keymap(keymap, NULL, NUM_ROWS, NUM_COLS,
kbd->keycodes, input_dev);
if (error) {
dev_err(&pdev->dev, "Failed to build keymap\n");
goto err_put_clk;
}
if (kbd->rep)
__set_bit(EV_REP, input_dev->evbit);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
input_dev->keycode = kbd->keycodes;
input_dev->keycodesize = sizeof(kbd->keycodes[0]);
input_dev->keycodemax = ARRAY_SIZE(kbd->keycodes);
matrix_keypad_build_keymap(keymap, ROW_SHIFT,
input_dev->keycode, input_dev->keybit);
input_set_drvdata(input_dev, kbd);
error = request_irq(irq, spear_kbd_interrupt, 0, "keyboard", kbd);
......@@ -317,6 +350,14 @@ static int spear_kbd_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(spear_kbd_pm_ops, spear_kbd_suspend, spear_kbd_resume);
#ifdef CONFIG_OF
static const struct of_device_id spear_kbd_id_table[] = {
{ .compatible = "st,spear300-kbd" },
{}
};
MODULE_DEVICE_TABLE(of, spear_kbd_id_table);
#endif
static struct platform_driver spear_kbd_driver = {
.probe = spear_kbd_probe,
.remove = __devexit_p(spear_kbd_remove),
......@@ -324,6 +365,7 @@ static struct platform_driver spear_kbd_driver = {
.name = "keyboard",
.owner = THIS_MODULE,
.pm = &spear_kbd_pm_ops,
.of_match_table = of_match_ptr(spear_kbd_id_table),
},
};
module_platform_driver(spear_kbd_driver);
......
......@@ -289,19 +289,17 @@ static int __devinit stmpe_keypad_probe(struct platform_device *pdev)
input->id.bustype = BUS_I2C;
input->dev.parent = &pdev->dev;
input_set_capability(input, EV_MSC, MSC_SCAN);
ret = matrix_keypad_build_keymap(plat->keymap_data, NULL,
STMPE_KEYPAD_MAX_ROWS,
STMPE_KEYPAD_MAX_COLS,
keypad->keymap, input);
if (ret)
goto out_freeinput;
__set_bit(EV_KEY, input->evbit);
input_set_capability(input, EV_MSC, MSC_SCAN);
if (!plat->no_autorepeat)
__set_bit(EV_REP, input->evbit);
input->keycode = keypad->keymap;
input->keycodesize = sizeof(keypad->keymap[0]);
input->keycodemax = ARRAY_SIZE(keypad->keymap);
matrix_keypad_build_keymap(plat->keymap_data, STMPE_KEYPAD_ROW_SHIFT,
input->keycode, input->keybit);
for (i = 0; i < plat->keymap_data->keymap_size; i++) {
unsigned int key = plat->keymap_data->keymap[i];
......
......@@ -170,15 +170,4 @@ static struct serio_driver skbd_drv = {
.disconnect = skbd_disconnect,
};
static int __init skbd_init(void)
{
return serio_register_driver(&skbd_drv);
}
static void __exit skbd_exit(void)
{
serio_unregister_driver(&skbd_drv);
}
module_init(skbd_init);
module_exit(skbd_exit);
module_serio_driver(skbd_drv);
......@@ -369,19 +369,4 @@ static struct serio_driver sunkbd_drv = {
.disconnect = sunkbd_disconnect,
};
/*
* The functions for insering/removing us as a module.
*/
static int __init sunkbd_init(void)
{
return serio_register_driver(&sunkbd_drv);
}
static void __exit sunkbd_exit(void)
{
serio_unregister_driver(&sunkbd_drv);
}
module_init(sunkbd_init);
module_exit(sunkbd_exit);
module_serio_driver(sunkbd_drv);
......@@ -78,7 +78,7 @@
* @input: pointer to input device object
* @board: keypad platform device
* @krow: number of rows
* @kcol: number of coloumns
* @kcol: number of columns
* @keymap: matrix scan code table for keycodes
* @keypad_stopped: holds keypad status
*/
......@@ -96,21 +96,15 @@ static int tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad)
{
int ret;
struct tc3589x *tc3589x = keypad->tc3589x;
u8 settle_time = keypad->board->settle_time;
u8 dbounce_period = keypad->board->debounce_period;
u8 rows = keypad->board->krow & 0xf; /* mask out the nibble */
u8 column = keypad->board->kcol & 0xf; /* mask out the nibble */
/* validate platform configurations */
if (keypad->board->kcol > TC3589x_MAX_KPCOL ||
keypad->board->krow > TC3589x_MAX_KPROW ||
keypad->board->debounce_period > TC3589x_MAX_DEBOUNCE_SETTLE ||
keypad->board->settle_time > TC3589x_MAX_DEBOUNCE_SETTLE)
const struct tc3589x_keypad_platform_data *board = keypad->board;
/* validate platform configuration */
if (board->kcol > TC3589x_MAX_KPCOL || board->krow > TC3589x_MAX_KPROW)
return -EINVAL;
/* configure KBDSIZE 4 LSbits for cols and 4 MSbits for rows */
ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSIZE,
(rows << KP_ROW_SHIFT) | column);
(board->krow << KP_ROW_SHIFT) | board->kcol);
if (ret < 0)
return ret;
......@@ -124,12 +118,14 @@ static int tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad)
return ret;
/* Configure settle time */
ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSETTLE_REG, settle_time);
ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSETTLE_REG,
board->settle_time);
if (ret < 0)
return ret;
/* Configure debounce time */
ret = tc3589x_reg_write(tc3589x, TC3589x_KBDBOUNCE, dbounce_period);
ret = tc3589x_reg_write(tc3589x, TC3589x_KBDBOUNCE,
board->debounce_period);
if (ret < 0)
return ret;
......@@ -337,23 +333,22 @@ static int __devinit tc3589x_keypad_probe(struct platform_device *pdev)
input->name = pdev->name;
input->dev.parent = &pdev->dev;
input->keycode = keypad->keymap;
input->keycodesize = sizeof(keypad->keymap[0]);
input->keycodemax = ARRAY_SIZE(keypad->keymap);
input->open = tc3589x_keypad_open;
input->close = tc3589x_keypad_close;
input_set_drvdata(input, keypad);
error = matrix_keypad_build_keymap(plat->keymap_data, NULL,
TC3589x_MAX_KPROW, TC3589x_MAX_KPCOL,
keypad->keymap, input);
if (error) {
dev_err(&pdev->dev, "Failed to build keymap\n");
goto err_free_mem;
}
input_set_capability(input, EV_MSC, MSC_SCAN);
__set_bit(EV_KEY, input->evbit);
if (!plat->no_autorepeat)
__set_bit(EV_REP, input->evbit);
matrix_keypad_build_keymap(plat->keymap_data, 0x3,
input->keycode, input->keybit);
input_set_drvdata(input, keypad);
error = request_threaded_irq(irq, NULL,
tc3589x_keypad_irq, plat->irqtype,
......
......@@ -342,21 +342,20 @@ static int __devinit tca8418_keypad_probe(struct i2c_client *client,
input->id.product = 0x001;
input->id.version = 0x0001;
input->keycode = keypad_data->keymap;
input->keycodesize = sizeof(keypad_data->keymap[0]);
input->keycodemax = max_keys;
error = matrix_keypad_build_keymap(pdata->keymap_data, NULL,
pdata->rows, pdata->cols,
keypad_data->keymap, input);
if (error) {
dev_dbg(&client->dev, "Failed to build keymap\n");
goto fail2;
}
__set_bit(EV_KEY, input->evbit);
if (pdata->rep)
__set_bit(EV_REP, input->evbit);
input_set_capability(input, EV_MSC, MSC_SCAN);
input_set_drvdata(input, keypad_data);
matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
input->keycode, input->keybit);
if (pdata->irq_is_gpio)
client->irq = gpio_to_irq(client->irq);
......
......@@ -619,8 +619,8 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata,
}
#ifdef CONFIG_OF
static struct tegra_kbc_platform_data * __devinit
tegra_kbc_dt_parse_pdata(struct platform_device *pdev)
static struct tegra_kbc_platform_data * __devinit tegra_kbc_dt_parse_pdata(
struct platform_device *pdev)
{
struct tegra_kbc_platform_data *pdata;
struct device_node *np = pdev->dev.of_node;
......@@ -660,10 +660,6 @@ tegra_kbc_dt_parse_pdata(struct platform_device *pdev)
pdata->pin_cfg[KBC_MAX_ROW + i].type = PIN_CFG_COL;
}
pdata->keymap_data = matrix_keyboard_of_fill_keymap(np, "linux,keymap");
/* FIXME: Add handling of linux,fn-keymap here */
return pdata;
}
#else
......@@ -674,10 +670,36 @@ static inline struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata(
}
#endif
static int __devinit tegra_kbd_setup_keymap(struct tegra_kbc *kbc)
{
const struct tegra_kbc_platform_data *pdata = kbc->pdata;
const struct matrix_keymap_data *keymap_data = pdata->keymap_data;
unsigned int keymap_rows = KBC_MAX_KEY;
int retval;
if (keymap_data && pdata->use_fn_map)
keymap_rows *= 2;
retval = matrix_keypad_build_keymap(keymap_data, NULL,
keymap_rows, KBC_MAX_COL,
kbc->keycode, kbc->idev);
if (retval == -ENOSYS || retval == -ENOENT) {
/*
* If there is no OF support in kernel or keymap
* property is missing, use default keymap.
*/
retval = matrix_keypad_build_keymap(
&tegra_kbc_default_keymap_data, NULL,
keymap_rows, KBC_MAX_COL,
kbc->keycode, kbc->idev);
}
return retval;
}
static int __devinit tegra_kbc_probe(struct platform_device *pdev)
{
const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data;
const struct matrix_keymap_data *keymap_data;
struct tegra_kbc *kbc;
struct input_dev *input_dev;
struct resource *res;
......@@ -757,29 +779,26 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev)
kbc->repoll_dly = KBC_ROW_SCAN_DLY + scan_time_rows + pdata->repeat_cnt;
kbc->repoll_dly = DIV_ROUND_UP(kbc->repoll_dly, KBC_CYCLE_MS);
kbc->wakeup_key = pdata->wakeup_key;
kbc->use_fn_map = pdata->use_fn_map;
kbc->use_ghost_filter = pdata->use_ghost_filter;
input_dev->name = pdev->name;
input_dev->id.bustype = BUS_HOST;
input_dev->dev.parent = &pdev->dev;
input_dev->open = tegra_kbc_open;
input_dev->close = tegra_kbc_close;
input_set_drvdata(input_dev, kbc);
err = tegra_kbd_setup_keymap(kbc);
if (err) {
dev_err(&pdev->dev, "failed to setup keymap\n");
goto err_put_clk;
}
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
__set_bit(EV_REP, input_dev->evbit);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
input_dev->keycode = kbc->keycode;
input_dev->keycodesize = sizeof(kbc->keycode[0]);
input_dev->keycodemax = KBC_MAX_KEY;
if (pdata->use_fn_map)
input_dev->keycodemax *= 2;
kbc->use_fn_map = pdata->use_fn_map;
kbc->use_ghost_filter = pdata->use_ghost_filter;
keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data;
matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT,
input_dev->keycode, input_dev->keybit);
kbc->wakeup_key = pdata->wakeup_key;
input_set_drvdata(input_dev, kbc);
err = request_irq(kbc->irq, tegra_kbc_isr,
IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH, pdev->name, kbc);
......@@ -799,9 +818,6 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, kbc);
device_init_wakeup(&pdev->dev, pdata->wakeup);
if (!pdev->dev.platform_data)
matrix_keyboard_of_free_keymap(pdata->keymap_data);
return 0;
err_free_irq:
......@@ -816,10 +832,8 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev)
input_free_device(input_dev);
kfree(kbc);
err_free_pdata:
if (!pdev->dev.platform_data) {
matrix_keyboard_of_free_keymap(pdata->keymap_data);
if (!pdev->dev.platform_data)
kfree(pdata);
}
return err;
}
......
......@@ -247,15 +247,11 @@ static int __devinit keypad_probe(struct platform_device *pdev)
error = -ENOMEM;
goto error_input;
}
input_set_drvdata(kp->input_dev, kp);
kp->input_dev->name = pdev->name;
kp->input_dev->dev.parent = &pdev->dev;
kp->input_dev->open = keypad_start;
kp->input_dev->close = keypad_stop;
kp->input_dev->evbit[0] = BIT_MASK(EV_KEY);
if (!pdata->no_autorepeat)
kp->input_dev->evbit[0] |= BIT_MASK(EV_REP);
clk_enable(kp->clk);
rev = keypad_read(kp, rev);
......@@ -264,15 +260,20 @@ static int __devinit keypad_probe(struct platform_device *pdev)
kp->input_dev->id.version = ((rev >> 16) & 0xfff);
clk_disable(kp->clk);
kp->input_dev->keycode = kp->keycodes;
kp->input_dev->keycodesize = sizeof(kp->keycodes[0]);
kp->input_dev->keycodemax = kp->rows << kp->row_shift;
matrix_keypad_build_keymap(keymap_data, kp->row_shift, kp->keycodes,
kp->input_dev->keybit);
error = matrix_keypad_build_keymap(keymap_data, NULL,
kp->rows, kp->cols,
kp->keycodes, kp->input_dev);
if (error) {
dev_err(dev, "Failed to build keymap\n");
goto error_reg;
}
if (!pdata->no_autorepeat)
kp->input_dev->evbit[0] |= BIT_MASK(EV_REP);
input_set_capability(kp->input_dev, EV_MSC, MSC_SCAN);
input_set_drvdata(kp->input_dev, kp);
error = input_register_device(kp->input_dev);
if (error < 0) {
dev_err(dev, "Could not register input device\n");
......
......@@ -361,14 +361,6 @@ static int __devinit twl4030_kp_probe(struct platform_device *pdev)
kp->irq = platform_get_irq(pdev, 0);
/* setup input device */
__set_bit(EV_KEY, input->evbit);
/* Enable auto repeat feature of Linux input subsystem */
if (pdata->rep)
__set_bit(EV_REP, input->evbit);
input_set_capability(input, EV_MSC, MSC_SCAN);
input->name = "TWL4030 Keypad";
input->phys = "twl4030_keypad/input0";
input->dev.parent = &pdev->dev;
......@@ -378,12 +370,19 @@ static int __devinit twl4030_kp_probe(struct platform_device *pdev)
input->id.product = 0x0001;
input->id.version = 0x0003;
input->keycode = kp->keymap;
input->keycodesize = sizeof(kp->keymap[0]);
input->keycodemax = ARRAY_SIZE(kp->keymap);
error = matrix_keypad_build_keymap(keymap_data, NULL,
TWL4030_MAX_ROWS,
1 << TWL4030_ROW_SHIFT,
kp->keymap, input);
if (error) {
dev_err(kp->dbg_dev, "Failed to build keymap\n");
goto err1;
}
matrix_keypad_build_keymap(keymap_data, TWL4030_ROW_SHIFT,
input->keycode, input->keybit);
input_set_capability(input, EV_MSC, MSC_SCAN);
/* Enable auto repeat feature of Linux input subsystem */
if (pdata->rep)
__set_bit(EV_REP, input->evbit);
error = input_register_device(input);
if (error) {
......
......@@ -42,7 +42,8 @@
#define KGET_RAW(n) (((n) & KEY0R) >> 3)
#define KGET_COLUMN(n) ((n) & KEY0C)
#define W90P910_MAX_KEY_NUM (8 * 8)
#define W90P910_NUM_ROWS 8
#define W90P910_NUM_COLS 8
#define W90P910_ROW_SHIFT 3
struct w90p910_keypad {
......@@ -51,7 +52,7 @@ struct w90p910_keypad {
struct input_dev *input_dev;
void __iomem *mmio_base;
int irq;
unsigned short keymap[W90P910_MAX_KEY_NUM];
unsigned short keymap[W90P910_NUM_ROWS * W90P910_NUM_COLS];
};
static void w90p910_keypad_scan_matrix(struct w90p910_keypad *keypad,
......@@ -190,17 +191,13 @@ static int __devinit w90p910_keypad_probe(struct platform_device *pdev)
input_dev->close = w90p910_keypad_close;
input_dev->dev.parent = &pdev->dev;
input_dev->keycode = keypad->keymap;
input_dev->keycodesize = sizeof(keypad->keymap[0]);
input_dev->keycodemax = ARRAY_SIZE(keypad->keymap);
input_set_drvdata(input_dev, keypad);
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
matrix_keypad_build_keymap(keymap_data, W90P910_ROW_SHIFT,
input_dev->keycode, input_dev->keybit);
error = matrix_keypad_build_keymap(keymap_data, NULL,
W90P910_NUM_ROWS, W90P910_NUM_COLS,
keypad->keymap, input_dev);
if (error) {
dev_err(&pdev->dev, "failed to build keymap\n");
goto failed_put_clk;
}
error = request_irq(keypad->irq, w90p910_keypad_irq_handler,
0, pdev->name, keypad);
......@@ -209,6 +206,10 @@ static int __devinit w90p910_keypad_probe(struct platform_device *pdev)
goto failed_put_clk;
}
__set_bit(EV_REP, input_dev->evbit);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
input_set_drvdata(input_dev, keypad);
/* Register the input device */
error = input_register_device(input_dev);
if (error) {
......
......@@ -169,15 +169,4 @@ static struct serio_driver xtkbd_drv = {
.disconnect = xtkbd_disconnect,
};
static int __init xtkbd_init(void)
{
return serio_register_driver(&xtkbd_drv);
}
static void __exit xtkbd_exit(void)
{
serio_unregister_driver(&xtkbd_drv);
}
module_init(xtkbd_init);
module_exit(xtkbd_exit);
module_serio_driver(xtkbd_drv);
/*
* Helpers for matrix keyboard bindings
*
* Copyright (C) 2012 Google, Inc
*
* Author:
* Olof Johansson <olof@lixom.net>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/input.h>
#include <linux/of.h>
#include <linux/export.h>
#include <linux/input/matrix_keypad.h>
static bool matrix_keypad_map_key(struct input_dev *input_dev,
unsigned int rows, unsigned int cols,
unsigned int row_shift, unsigned int key)
{
unsigned short *keymap = input_dev->keycode;
unsigned int row = KEY_ROW(key);
unsigned int col = KEY_COL(key);
unsigned short code = KEY_VAL(key);
if (row >= rows || col >= cols) {
dev_err(input_dev->dev.parent,
"%s: invalid keymap entry 0x%x (row: %d, col: %d, rows: %d, cols: %d)\n",
__func__, key, row, col, rows, cols);
return false;
}
keymap[MATRIX_SCAN_CODE(row, col, row_shift)] = code;
__set_bit(code, input_dev->keybit);
return true;
}
#ifdef CONFIG_OF
static int matrix_keypad_parse_of_keymap(const char *propname,
unsigned int rows, unsigned int cols,
struct input_dev *input_dev)
{
struct device *dev = input_dev->dev.parent;
struct device_node *np = dev->of_node;
unsigned int row_shift = get_count_order(cols);
unsigned int max_keys = rows << row_shift;
unsigned int proplen, i, size;
const __be32 *prop;
if (!np)
return -ENOENT;
if (!propname)
propname = "linux,keymap";
prop = of_get_property(np, propname, &proplen);
if (!prop) {
dev_err(dev, "OF: %s property not defined in %s\n",
propname, np->full_name);
return -ENOENT;
}
if (proplen % sizeof(u32)) {
dev_err(dev, "OF: Malformed keycode property %s in %s\n",
propname, np->full_name);
return -EINVAL;
}
size = proplen / sizeof(u32);
if (size > max_keys) {
dev_err(dev, "OF: %s size overflow\n", propname);
return -EINVAL;
}
for (i = 0; i < size; i++) {
unsigned int key = be32_to_cpup(prop + i);
if (!matrix_keypad_map_key(input_dev, rows, cols,
row_shift, key))
return -EINVAL;
}
return 0;
}
#else
static int matrix_keypad_parse_of_keymap(const char *propname,
unsigned int rows, unsigned int cols,
struct input_dev *input_dev)
{
return -ENOSYS;
}
#endif
/**
* matrix_keypad_build_keymap - convert platform keymap into matrix keymap
* @keymap_data: keymap supplied by the platform code
* @keymap_name: name of device tree property containing keymap (if device
* tree support is enabled).
* @rows: number of rows in target keymap array
* @cols: number of cols in target keymap array
* @keymap: expanded version of keymap that is suitable for use by
* matrix keyboard driver
* @input_dev: input devices for which we are setting up the keymap
*
* This function converts platform keymap (encoded with KEY() macro) into
* an array of keycodes that is suitable for using in a standard matrix
* keyboard driver that uses row and col as indices.
*
* If @keymap_data is not supplied and device tree support is enabled
* it will attempt load the keymap from property specified by @keymap_name
* argument (or "linux,keymap" if @keymap_name is %NULL).
*
* Callers are expected to set up input_dev->dev.parent before calling this
* function.
*/
int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
const char *keymap_name,
unsigned int rows, unsigned int cols,
unsigned short *keymap,
struct input_dev *input_dev)
{
unsigned int row_shift = get_count_order(cols);
int i;
int error;
input_dev->keycode = keymap;
input_dev->keycodesize = sizeof(*keymap);
input_dev->keycodemax = rows << row_shift;
__set_bit(EV_KEY, input_dev->evbit);
if (keymap_data) {
for (i = 0; i < keymap_data->keymap_size; i++) {
unsigned int key = keymap_data->keymap[i];
if (!matrix_keypad_map_key(input_dev, rows, cols,
row_shift, key))
return -EINVAL;
}
} else {
error = matrix_keypad_parse_of_keymap(keymap_name, rows, cols,
input_dev);
if (error)
return error;
}
__clear_bit(KEY_RESERVED, input_dev->keybit);
return 0;
}
EXPORT_SYMBOL(matrix_keypad_build_keymap);
......@@ -318,7 +318,7 @@ struct cma3000_accl_data *cma3000_init(struct device *dev, int irq,
mutex_init(&data->mutex);
data->mode = pdata->mode;
if (data->mode < CMAMODE_DEFAULT || data->mode > CMAMODE_POFF) {
if (data->mode > CMAMODE_POFF) {
data->mode = CMAMODE_MOTDET;
dev_warn(dev,
"Invalid mode specified, assuming Motion Detect\n");
......
......@@ -367,7 +367,7 @@ static int __devinit mpu3050_probe(struct i2c_client *client,
error = request_threaded_irq(client->irq,
NULL, mpu3050_interrupt_thread,
IRQF_TRIGGER_RISING,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"mpu3050", sensor);
if (error) {
dev_err(&client->dev,
......
......@@ -27,6 +27,7 @@
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/workqueue.h>
#include <linux/input.h>
#include <linux/mfd/twl6040.h>
......@@ -258,10 +259,13 @@ static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL);
static int __devinit twl6040_vibra_probe(struct platform_device *pdev)
{
struct twl6040_vibra_data *pdata = pdev->dev.platform_data;
struct device_node *node = pdev->dev.of_node;
struct vibra_info *info;
int vddvibl_uV = 0;
int vddvibr_uV = 0;
int ret;
if (!pdata) {
if (!pdata && !node) {
dev_err(&pdev->dev, "platform_data not available\n");
return -EINVAL;
}
......@@ -273,11 +277,26 @@ static int __devinit twl6040_vibra_probe(struct platform_device *pdev)
}
info->dev = &pdev->dev;
info->twl6040 = dev_get_drvdata(pdev->dev.parent);
info->vibldrv_res = pdata->vibldrv_res;
info->vibrdrv_res = pdata->vibrdrv_res;
info->viblmotor_res = pdata->viblmotor_res;
info->vibrmotor_res = pdata->vibrmotor_res;
if (pdata) {
info->vibldrv_res = pdata->vibldrv_res;
info->vibrdrv_res = pdata->vibrdrv_res;
info->viblmotor_res = pdata->viblmotor_res;
info->vibrmotor_res = pdata->vibrmotor_res;
vddvibl_uV = pdata->vddvibl_uV;
vddvibr_uV = pdata->vddvibr_uV;
} else {
of_property_read_u32(node, "vibldrv_res", &info->vibldrv_res);
of_property_read_u32(node, "vibrdrv_res", &info->vibrdrv_res);
of_property_read_u32(node, "viblmotor_res",
&info->viblmotor_res);
of_property_read_u32(node, "vibrmotor_res",
&info->vibrmotor_res);
of_property_read_u32(node, "vddvibl_uV", &vddvibl_uV);
of_property_read_u32(node, "vddvibr_uV", &vddvibr_uV);
}
if ((!info->vibldrv_res && !info->viblmotor_res) ||
(!info->vibrdrv_res && !info->vibrmotor_res)) {
dev_err(info->dev, "invalid vibra driver/motor resistance\n");
......@@ -339,10 +358,9 @@ static int __devinit twl6040_vibra_probe(struct platform_device *pdev)
goto err_regulator;
}
if (pdata->vddvibl_uV) {
if (vddvibl_uV) {
ret = regulator_set_voltage(info->supplies[0].consumer,
pdata->vddvibl_uV,
pdata->vddvibl_uV);
vddvibl_uV, vddvibl_uV);
if (ret) {
dev_err(info->dev, "failed to set VDDVIBL volt %d\n",
ret);
......@@ -350,10 +368,9 @@ static int __devinit twl6040_vibra_probe(struct platform_device *pdev)
}
}
if (pdata->vddvibr_uV) {
if (vddvibr_uV) {
ret = regulator_set_voltage(info->supplies[1].consumer,
pdata->vddvibr_uV,
pdata->vddvibr_uV);
vddvibr_uV, vddvibr_uV);
if (ret) {
dev_err(info->dev, "failed to set VDDVIBR volt %d\n",
ret);
......@@ -401,6 +418,12 @@ static int __devexit twl6040_vibra_remove(struct platform_device *pdev)
return 0;
}
static const struct of_device_id twl6040_vibra_of_match[] = {
{.compatible = "ti,twl6040-vibra", },
{ },
};
MODULE_DEVICE_TABLE(of, twl6040_vibra_of_match);
static struct platform_driver twl6040_vibra_driver = {
.probe = twl6040_vibra_probe,
.remove = __devexit_p(twl6040_vibra_remove),
......@@ -408,6 +431,7 @@ static struct platform_driver twl6040_vibra_driver = {
.name = "twl6040-vibra",
.owner = THIS_MODULE,
.pm = &twl6040_vibra_pm_ops,
.of_match_table = twl6040_vibra_of_match,
},
};
module_platform_driver(twl6040_vibra_driver);
......
......@@ -339,4 +339,16 @@ config MOUSE_SYNAPTICS_USB
To compile this driver as a module, choose M here: the
module will be called synaptics_usb.
config MOUSE_NAVPOINT_PXA27x
tristate "Synaptics NavPoint (PXA27x SSP/SPI)"
depends on PXA27x && PXA_SSP
help
This driver adds support for the Synaptics NavPoint touchpad connected
to a PXA27x SSP port in SPI slave mode. The device emulates a mouse;
a tap or tap-and-a-half drag gesture emulates the left mouse button.
For example, use the xf86-input-evdev driver for an X pointing device.
To compile this driver as a module, choose M here: the
module will be called navpoint.
endif
......@@ -12,6 +12,7 @@ obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o
obj-$(CONFIG_MOUSE_INPORT) += inport.o
obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o
obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o
obj-$(CONFIG_MOUSE_NAVPOINT_PXA27x) += navpoint.o
obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o
obj-$(CONFIG_MOUSE_PS2) += psmouse.o
obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o
......
......@@ -553,10 +553,7 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse)
alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4);
input_mt_report_finger_count(dev, fingers);
input_report_key(dev, BTN_LEFT, left);
input_report_key(dev, BTN_RIGHT, right);
......@@ -604,10 +601,54 @@ static void alps_process_packet_v3(struct psmouse *psmouse)
static void alps_process_packet_v4(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
unsigned char *packet = psmouse->packet;
struct input_dev *dev = psmouse->dev;
int offset;
int x, y, z;
int left, right;
int x1, y1, x2, y2;
int fingers = 0;
unsigned int x_bitmap, y_bitmap;
/*
* v4 has a 6-byte encoding for bitmap data, but this data is
* broken up between 3 normal packets. Use priv->multi_packet to
* track our position in the bitmap packet.
*/
if (packet[6] & 0x40) {
/* sync, reset position */
priv->multi_packet = 0;
}
if (WARN_ON_ONCE(priv->multi_packet > 2))
return;
offset = 2 * priv->multi_packet;
priv->multi_data[offset] = packet[6];
priv->multi_data[offset + 1] = packet[7];
if (++priv->multi_packet > 2) {
priv->multi_packet = 0;
x_bitmap = ((priv->multi_data[2] & 0x1f) << 10) |
((priv->multi_data[3] & 0x60) << 3) |
((priv->multi_data[0] & 0x3f) << 2) |
((priv->multi_data[1] & 0x60) >> 5);
y_bitmap = ((priv->multi_data[5] & 0x01) << 10) |
((priv->multi_data[3] & 0x1f) << 5) |
(priv->multi_data[1] & 0x1f);
fingers = alps_process_bitmap(x_bitmap, y_bitmap,
&x1, &y1, &x2, &y2);
/* Store MT data.*/
priv->fingers = fingers;
priv->x1 = x1;
priv->x2 = x2;
priv->y1 = y1;
priv->y2 = y2;
}
left = packet[4] & 0x01;
right = packet[4] & 0x02;
......@@ -617,21 +658,41 @@ static void alps_process_packet_v4(struct psmouse *psmouse)
y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
z = packet[5] & 0x7f;
/*
* If there were no contacts in the bitmap, use ST
* points in MT reports.
* If there were two contacts or more, report MT data.
*/
if (priv->fingers < 2) {
x1 = x;
y1 = y;
fingers = z > 0 ? 1 : 0;
} else {
fingers = priv->fingers;
x1 = priv->x1;
x2 = priv->x2;
y1 = priv->y1;
y2 = priv->y2;
}
if (z >= 64)
input_report_key(dev, BTN_TOUCH, 1);
else
input_report_key(dev, BTN_TOUCH, 0);
alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
input_mt_report_finger_count(dev, fingers);
input_report_key(dev, BTN_LEFT, left);
input_report_key(dev, BTN_RIGHT, right);
if (z > 0) {
input_report_abs(dev, ABS_X, x);
input_report_abs(dev, ABS_Y, y);
}
input_report_abs(dev, ABS_PRESSURE, z);
input_report_key(dev, BTN_TOOL_FINGER, z > 0);
input_report_key(dev, BTN_LEFT, left);
input_report_key(dev, BTN_RIGHT, right);
input_sync(dev);
}
......@@ -1557,6 +1618,7 @@ int alps_init(struct psmouse *psmouse)
input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0);
break;
case ALPS_PROTO_V3:
case ALPS_PROTO_V4:
set_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
input_mt_init_slots(dev1, 2);
input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0);
......@@ -1565,8 +1627,7 @@ int alps_init(struct psmouse *psmouse)
set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit);
set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit);
set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
/* fall through */
case ALPS_PROTO_V4:
input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0);
input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0);
break;
......
......@@ -39,6 +39,8 @@ struct alps_data {
int prev_fin; /* Finger bit from previous packet */
int multi_packet; /* Multi-packet data in progress */
unsigned char multi_data[6]; /* Saved multi-packet data */
int x1, x2, y1, y2; /* Coordinates from last MT report */
int fingers; /* Number of fingers from MT report */
u8 quirks;
struct timer_list timer;
};
......
/*
* Synaptics NavPoint (PXA27x SSP/SPI) driver.
*
* Copyright (C) 2012 Paul Parsons <lost.distance@yahoo.com>
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/input/navpoint.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/pxa2xx_ssp.h>
#include <linux/slab.h>
/*
* Synaptics Modular Embedded Protocol: Module Packet Format.
* Module header byte 2:0 = Length (# bytes that follow)
* Module header byte 4:3 = Control
* Module header byte 7:5 = Module Address
*/
#define HEADER_LENGTH(byte) ((byte) & 0x07)
#define HEADER_CONTROL(byte) (((byte) >> 3) & 0x03)
#define HEADER_ADDRESS(byte) ((byte) >> 5)
struct navpoint {
struct ssp_device *ssp;
struct input_dev *input;
struct device *dev;
int gpio;
int index;
u8 data[1 + HEADER_LENGTH(0xff)];
};
/*
* Initialization values for SSCR0_x, SSCR1_x, SSSR_x.
*/
static const u32 sscr0 = 0
| SSCR0_TUM /* TIM = 1; No TUR interrupts */
| SSCR0_RIM /* RIM = 1; No ROR interrupts */
| SSCR0_SSE /* SSE = 1; SSP enabled */
| SSCR0_Motorola /* FRF = 0; Motorola SPI */
| SSCR0_DataSize(16) /* DSS = 15; Data size = 16-bit */
;
static const u32 sscr1 = 0
| SSCR1_SCFR /* SCFR = 1; SSPSCLK only during transfers */
| SSCR1_SCLKDIR /* SCLKDIR = 1; Slave mode */
| SSCR1_SFRMDIR /* SFRMDIR = 1; Slave mode */
| SSCR1_RWOT /* RWOT = 1; Receive without transmit mode */
| SSCR1_RxTresh(1) /* RFT = 0; Receive FIFO threshold = 1 */
| SSCR1_SPH /* SPH = 1; SSPSCLK inactive 0.5 + 1 cycles */
| SSCR1_RIE /* RIE = 1; Receive FIFO interrupt enabled */
;
static const u32 sssr = 0
| SSSR_BCE /* BCE = 1; Clear BCE */
| SSSR_TUR /* TUR = 1; Clear TUR */
| SSSR_EOC /* EOC = 1; Clear EOC */
| SSSR_TINT /* TINT = 1; Clear TINT */
| SSSR_PINT /* PINT = 1; Clear PINT */
| SSSR_ROR /* ROR = 1; Clear ROR */
;
/*
* MEP Query $22: Touchpad Coordinate Range Query is not supported by
* the NavPoint module, so sampled values provide the default limits.
*/
#define NAVPOINT_X_MIN 1278
#define NAVPOINT_X_MAX 5340
#define NAVPOINT_Y_MIN 1572
#define NAVPOINT_Y_MAX 4396
#define NAVPOINT_PRESSURE_MIN 0
#define NAVPOINT_PRESSURE_MAX 255
static void navpoint_packet(struct navpoint *navpoint)
{
int finger;
int gesture;
int x, y, z;
switch (navpoint->data[0]) {
case 0xff: /* Garbage (packet?) between reset and Hello packet */
case 0x00: /* Module 0, NULL packet */
break;
case 0x0e: /* Module 0, Absolute packet */
finger = (navpoint->data[1] & 0x01);
gesture = (navpoint->data[1] & 0x02);
x = ((navpoint->data[2] & 0x1f) << 8) | navpoint->data[3];
y = ((navpoint->data[4] & 0x1f) << 8) | navpoint->data[5];
z = navpoint->data[6];
input_report_key(navpoint->input, BTN_TOUCH, finger);
input_report_abs(navpoint->input, ABS_X, x);
input_report_abs(navpoint->input, ABS_Y, y);
input_report_abs(navpoint->input, ABS_PRESSURE, z);
input_report_key(navpoint->input, BTN_TOOL_FINGER, finger);
input_report_key(navpoint->input, BTN_LEFT, gesture);
input_sync(navpoint->input);
break;
case 0x19: /* Module 0, Hello packet */
if ((navpoint->data[1] & 0xf0) == 0x10)
break;
/* FALLTHROUGH */
default:
dev_warn(navpoint->dev,
"spurious packet: data=0x%02x,0x%02x,...\n",
navpoint->data[0], navpoint->data[1]);
break;
}
}
static irqreturn_t navpoint_irq(int irq, void *dev_id)
{
struct navpoint *navpoint = dev_id;
struct ssp_device *ssp = navpoint->ssp;
irqreturn_t ret = IRQ_NONE;
u32 status;
status = pxa_ssp_read_reg(ssp, SSSR);
if (status & sssr) {
dev_warn(navpoint->dev,
"unexpected interrupt: status=0x%08x\n", status);
pxa_ssp_write_reg(ssp, SSSR, (status & sssr));
ret = IRQ_HANDLED;
}
while (status & SSSR_RNE) {
u32 data;
data = pxa_ssp_read_reg(ssp, SSDR);
navpoint->data[navpoint->index + 0] = (data >> 8);
navpoint->data[navpoint->index + 1] = data;
navpoint->index += 2;
if (HEADER_LENGTH(navpoint->data[0]) < navpoint->index) {
navpoint_packet(navpoint);
navpoint->index = 0;
}
status = pxa_ssp_read_reg(ssp, SSSR);
ret = IRQ_HANDLED;
}
return ret;
}
static void navpoint_up(struct navpoint *navpoint)
{
struct ssp_device *ssp = navpoint->ssp;
int timeout;
clk_prepare_enable(ssp->clk);
pxa_ssp_write_reg(ssp, SSCR1, sscr1);
pxa_ssp_write_reg(ssp, SSSR, sssr);
pxa_ssp_write_reg(ssp, SSTO, 0);
pxa_ssp_write_reg(ssp, SSCR0, sscr0); /* SSCR0_SSE written last */
/* Wait until SSP port is ready for slave clock operations */
for (timeout = 100; timeout != 0; --timeout) {
if (!(pxa_ssp_read_reg(ssp, SSSR) & SSSR_CSS))
break;
msleep(1);
}
if (timeout == 0)
dev_err(navpoint->dev,
"timeout waiting for SSSR[CSS] to clear\n");
if (gpio_is_valid(navpoint->gpio))
gpio_set_value(navpoint->gpio, 1);
}
static void navpoint_down(struct navpoint *navpoint)
{
struct ssp_device *ssp = navpoint->ssp;
if (gpio_is_valid(navpoint->gpio))
gpio_set_value(navpoint->gpio, 0);
pxa_ssp_write_reg(ssp, SSCR0, 0);
clk_disable_unprepare(ssp->clk);
}
static int navpoint_open(struct input_dev *input)
{
struct navpoint *navpoint = input_get_drvdata(input);
navpoint_up(navpoint);
return 0;
}
static void navpoint_close(struct input_dev *input)
{
struct navpoint *navpoint = input_get_drvdata(input);
navpoint_down(navpoint);
}
static int __devinit navpoint_probe(struct platform_device *pdev)
{
const struct navpoint_platform_data *pdata =
dev_get_platdata(&pdev->dev);
struct ssp_device *ssp;
struct input_dev *input;
struct navpoint *navpoint;
int error;
if (!pdata) {
dev_err(&pdev->dev, "no platform data\n");
return -EINVAL;
}
if (gpio_is_valid(pdata->gpio)) {
error = gpio_request_one(pdata->gpio, GPIOF_OUT_INIT_LOW,
"SYNAPTICS_ON");
if (error)
return error;
}
ssp = pxa_ssp_request(pdata->port, pdev->name);
if (!ssp) {
error = -ENODEV;
goto err_free_gpio;
}
/* HaRET does not disable devices before jumping into Linux */
if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) {
pxa_ssp_write_reg(ssp, SSCR0, 0);
dev_warn(&pdev->dev, "ssp%d already enabled\n", pdata->port);
}
navpoint = kzalloc(sizeof(*navpoint), GFP_KERNEL);
input = input_allocate_device();
if (!navpoint || !input) {
error = -ENOMEM;
goto err_free_mem;
}
navpoint->ssp = ssp;
navpoint->input = input;
navpoint->dev = &pdev->dev;
navpoint->gpio = pdata->gpio;
input->name = pdev->name;
input->dev.parent = &pdev->dev;
__set_bit(EV_KEY, input->evbit);
__set_bit(EV_ABS, input->evbit);
__set_bit(BTN_LEFT, input->keybit);
__set_bit(BTN_TOUCH, input->keybit);
__set_bit(BTN_TOOL_FINGER, input->keybit);
input_set_abs_params(input, ABS_X,
NAVPOINT_X_MIN, NAVPOINT_X_MAX, 0, 0);
input_set_abs_params(input, ABS_Y,
NAVPOINT_Y_MIN, NAVPOINT_Y_MAX, 0, 0);
input_set_abs_params(input, ABS_PRESSURE,
NAVPOINT_PRESSURE_MIN, NAVPOINT_PRESSURE_MAX,
0, 0);
input->open = navpoint_open;
input->close = navpoint_close;
input_set_drvdata(input, navpoint);
error = request_irq(ssp->irq, navpoint_irq, 0, pdev->name, navpoint);
if (error)
goto err_free_mem;
error = input_register_device(input);
if (error)
goto err_free_irq;
platform_set_drvdata(pdev, navpoint);
dev_dbg(&pdev->dev, "ssp%d, irq %d\n", pdata->port, ssp->irq);
return 0;
err_free_irq:
free_irq(ssp->irq, &pdev->dev);
err_free_mem:
input_free_device(input);
kfree(navpoint);
pxa_ssp_free(ssp);
err_free_gpio:
if (gpio_is_valid(pdata->gpio))
gpio_free(pdata->gpio);
return error;
}
static int __devexit navpoint_remove(struct platform_device *pdev)
{
const struct navpoint_platform_data *pdata =
dev_get_platdata(&pdev->dev);
struct navpoint *navpoint = platform_get_drvdata(pdev);
struct ssp_device *ssp = navpoint->ssp;
free_irq(ssp->irq, navpoint);
input_unregister_device(navpoint->input);
kfree(navpoint);
pxa_ssp_free(ssp);
if (gpio_is_valid(pdata->gpio))
gpio_free(pdata->gpio);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int navpoint_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct navpoint *navpoint = platform_get_drvdata(pdev);
struct input_dev *input = navpoint->input;
mutex_lock(&input->mutex);
if (input->users)
navpoint_down(navpoint);
mutex_unlock(&input->mutex);
return 0;
}
static int navpoint_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct navpoint *navpoint = platform_get_drvdata(pdev);
struct input_dev *input = navpoint->input;
mutex_lock(&input->mutex);
if (input->users)
navpoint_up(navpoint);
mutex_unlock(&input->mutex);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(navpoint_pm_ops, navpoint_suspend, navpoint_resume);
static struct platform_driver navpoint_driver = {
.probe = navpoint_probe,
.remove = __devexit_p(navpoint_remove),
.driver = {
.name = "navpoint",
.owner = THIS_MODULE,
.pm = &navpoint_pm_ops,
},
};
module_platform_driver(navpoint_driver);
MODULE_AUTHOR("Paul Parsons <lost.distance@yahoo.com>");
MODULE_DESCRIPTION("Synaptics NavPoint (PXA27x SSP/SPI) driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:navpoint");
......@@ -41,7 +41,7 @@
#define GET_ABS_Y(packet) ((packet[2] << 2) | (packet[3] & 0x03))
/** Driver version. */
static const char fsp_drv_ver[] = "1.0.0-K";
static const char fsp_drv_ver[] = "1.1.0-K";
/*
* Make sure that the value being sent to FSP will not conflict with
......@@ -303,6 +303,27 @@ static int fsp_get_revision(struct psmouse *psmouse, int *rev)
return 0;
}
static int fsp_get_sn(struct psmouse *psmouse, int *sn)
{
int v0, v1, v2;
int rc = -EIO;
/* production number since Cx is available at: 0x0b40 ~ 0x0b42 */
if (fsp_page_reg_write(psmouse, FSP_PAGE_0B))
goto out;
if (fsp_reg_read(psmouse, FSP_REG_SN0, &v0))
goto out;
if (fsp_reg_read(psmouse, FSP_REG_SN1, &v1))
goto out;
if (fsp_reg_read(psmouse, FSP_REG_SN2, &v2))
goto out;
*sn = (v0 << 16) | (v1 << 8) | v2;
rc = 0;
out:
fsp_page_reg_write(psmouse, FSP_PAGE_DEFAULT);
return rc;
}
static int fsp_get_buttons(struct psmouse *psmouse, int *btn)
{
static const int buttons[] = {
......@@ -1000,16 +1021,21 @@ static int fsp_reconnect(struct psmouse *psmouse)
int fsp_init(struct psmouse *psmouse)
{
struct fsp_data *priv;
int ver, rev;
int ver, rev, sn = 0;
int error;
if (fsp_get_version(psmouse, &ver) ||
fsp_get_revision(psmouse, &rev)) {
return -ENODEV;
}
if (ver >= FSP_VER_STL3888_C0) {
/* firmware information is only available since C0 */
fsp_get_sn(psmouse, &sn);
}
psmouse_info(psmouse, "Finger Sensing Pad, hw: %d.%d.%d, sw: %s\n",
ver >> 4, ver & 0x0F, rev, fsp_drv_ver);
psmouse_info(psmouse,
"Finger Sensing Pad, hw: %d.%d.%d, sn: %x, sw: %s\n",
ver >> 4, ver & 0x0F, rev, sn, fsp_drv_ver);
psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL);
if (!priv)
......
......@@ -65,6 +65,14 @@
#define FSP_BIT_SWC1_GST_GRP1 BIT(6)
#define FSP_BIT_SWC1_BX_COMPAT BIT(7)
#define FSP_PAGE_0B (0x0b)
#define FSP_PAGE_82 (0x82)
#define FSP_PAGE_DEFAULT FSP_PAGE_82
#define FSP_REG_SN0 (0x40)
#define FSP_REG_SN1 (0x41)
#define FSP_REG_SN2 (0x42)
/* Finger-sensing Pad packet formating related definitions */
/* absolute packet type */
......
......@@ -355,15 +355,4 @@ static struct serio_driver sermouse_drv = {
.disconnect = sermouse_disconnect,
};
static int __init sermouse_init(void)
{
return serio_register_driver(&sermouse_drv);
}
static void __exit sermouse_exit(void)
{
serio_unregister_driver(&sermouse_drv);
}
module_init(sermouse_init);
module_exit(sermouse_exit);
module_serio_driver(sermouse_drv);
......@@ -45,16 +45,6 @@
#define YMIN_NOMINAL 1408
#define YMAX_NOMINAL 4448
/*
* Synaptics touchpads report the y coordinate from bottom to top, which is
* opposite from what userspace expects.
* This function is used to invert y before reporting.
*/
static int synaptics_invert_y(int y)
{
return YMAX_NOMINAL + YMIN_NOMINAL - y;
}
/*****************************************************************************
* Stuff we need even when we do not want native Synaptics support
......@@ -111,6 +101,16 @@ void synaptics_reset(struct psmouse *psmouse)
* Synaptics communications functions
****************************************************************************/
/*
* Synaptics touchpads report the y coordinate from bottom to top, which is
* opposite from what userspace expects.
* This function is used to invert y before reporting.
*/
static int synaptics_invert_y(int y)
{
return YMAX_NOMINAL + YMIN_NOMINAL - y;
}
/*
* Send a command to the synpatics touchpad by special commands
*/
......
......@@ -548,16 +548,4 @@ static struct serio_driver vsxxxaa_drv = {
.disconnect = vsxxxaa_disconnect,
};
static int __init vsxxxaa_init(void)
{
return serio_register_driver(&vsxxxaa_drv);
}
static void __exit vsxxxaa_exit(void)
{
serio_unregister_driver(&vsxxxaa_drv);
}
module_init(vsxxxaa_init);
module_exit(vsxxxaa_exit);
module_serio_driver(vsxxxaa_drv);
/*
* Helpers for open firmware matrix keyboard bindings
*
* Copyright (C) 2012 Google, Inc
*
* Author:
* Olof Johansson <olof@lixom.net>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/input.h>
#include <linux/of.h>
#include <linux/input/matrix_keypad.h>
#include <linux/export.h>
#include <linux/gfp.h>
#include <linux/slab.h>
struct matrix_keymap_data *
matrix_keyboard_of_fill_keymap(struct device_node *np,
const char *propname)
{
struct matrix_keymap_data *kd;
u32 *keymap;
int proplen, i;
const __be32 *prop;
if (!np)
return NULL;
if (!propname)
propname = "linux,keymap";
prop = of_get_property(np, propname, &proplen);
if (!prop)
return NULL;
if (proplen % sizeof(u32)) {
pr_warn("Malformed keymap property %s in %s\n",
propname, np->full_name);
return NULL;
}
kd = kzalloc(sizeof(*kd), GFP_KERNEL);
if (!kd)
return NULL;
kd->keymap = keymap = kzalloc(proplen, GFP_KERNEL);
if (!kd->keymap) {
kfree(kd);
return NULL;
}
kd->keymap_size = proplen / sizeof(u32);
for (i = 0; i < kd->keymap_size; i++) {
u32 tmp = be32_to_cpup(prop + i);
int key_code, row, col;
row = (tmp >> 24) & 0xff;
col = (tmp >> 16) & 0xff;
key_code = tmp & 0xffff;
keymap[i] = KEY(row, col, key_code);
}
return kd;
}
EXPORT_SYMBOL_GPL(matrix_keyboard_of_fill_keymap);
void matrix_keyboard_of_free_keymap(const struct matrix_keymap_data *kd)
{
if (kd) {
kfree(kd->keymap);
kfree(kd);
}
}
EXPORT_SYMBOL_GPL(matrix_keyboard_of_free_keymap);
......@@ -206,6 +206,7 @@ static const struct pci_device_id pcips2_ids[] = {
},
{ 0, }
};
MODULE_DEVICE_TABLE(pci, pcips2_ids);
static struct pci_driver pcips2_driver = {
.name = "pcips2",
......@@ -214,20 +215,8 @@ static struct pci_driver pcips2_driver = {
.remove = __devexit_p(pcips2_remove),
};
static int __init pcips2_init(void)
{
return pci_register_driver(&pcips2_driver);
}
static void __exit pcips2_exit(void)
{
pci_unregister_driver(&pcips2_driver);
}
module_init(pcips2_init);
module_exit(pcips2_exit);
module_pci_driver(pcips2_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
MODULE_DESCRIPTION("PCI PS/2 keyboard/mouse driver");
MODULE_DEVICE_TABLE(pci, pcips2_ids);
......@@ -304,15 +304,4 @@ static struct serio_driver ps2mult_drv = {
.reconnect = ps2mult_reconnect,
};
static int __init ps2mult_init(void)
{
return serio_register_driver(&ps2mult_drv);
}
static void __exit ps2mult_exit(void)
{
serio_unregister_driver(&ps2mult_drv);
}
module_init(ps2mult_init);
module_exit(ps2mult_exit);
module_serio_driver(ps2mult_drv);
......@@ -165,31 +165,38 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer,
struct serio_raw *serio_raw = client->serio_raw;
char uninitialized_var(c);
ssize_t read = 0;
int retval;
int error;
if (serio_raw->dead)
return -ENODEV;
for (;;) {
if (serio_raw->dead)
return -ENODEV;
if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK))
return -EAGAIN;
if (serio_raw->head == serio_raw->tail &&
(file->f_flags & O_NONBLOCK))
return -EAGAIN;
retval = wait_event_interruptible(serio_raw->wait,
serio_raw->head != serio_raw->tail || serio_raw->dead);
if (retval)
return retval;
if (count == 0)
break;
if (serio_raw->dead)
return -ENODEV;
while (read < count && serio_raw_fetch_byte(serio_raw, &c)) {
if (put_user(c, buffer++))
return -EFAULT;
read++;
}
while (read < count && serio_raw_fetch_byte(serio_raw, &c)) {
if (put_user(c, buffer++)) {
retval = -EFAULT;
if (read)
break;
if (!(file->f_flags & O_NONBLOCK)) {
error = wait_event_interruptible(serio_raw->wait,
serio_raw->head != serio_raw->tail ||
serio_raw->dead);
if (error)
return error;
}
read++;
}
return read ?: retval;
return read;
}
static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
......@@ -197,8 +204,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
{
struct serio_raw_client *client = file->private_data;
struct serio_raw *serio_raw = client->serio_raw;
ssize_t written = 0;
int retval;
int retval = 0;
unsigned char c;
retval = mutex_lock_interruptible(&serio_raw_mutex);
......@@ -218,16 +224,20 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
retval = -EFAULT;
goto out;
}
if (serio_write(serio_raw->serio, c)) {
retval = -EIO;
/* Either signal error or partial write */
if (retval == 0)
retval = -EIO;
goto out;
}
written++;
retval++;
}
out:
mutex_unlock(&serio_raw_mutex);
return written ?: retval;
return retval;
}
static unsigned int serio_raw_poll(struct file *file, poll_table *wait)
......@@ -432,15 +442,4 @@ static struct serio_driver serio_raw_drv = {
.manual_bind = true,
};
static int __init serio_raw_init(void)
{
return serio_register_driver(&serio_raw_drv);
}
static void __exit serio_raw_exit(void)
{
serio_unregister_driver(&serio_raw_drv);
}
module_init(serio_raw_init);
module_exit(serio_raw_exit);
module_serio_driver(serio_raw_drv);
......@@ -73,7 +73,8 @@ struct xps2data {
spinlock_t lock;
void __iomem *base_address; /* virt. address of control registers */
unsigned int flags;
struct serio serio; /* serio */
struct serio *serio; /* serio */
struct device *dev;
};
/************************************/
......@@ -119,7 +120,7 @@ static irqreturn_t xps2_interrupt(int irq, void *dev_id)
/* Check which interrupt is active */
if (intr_sr & XPS2_IPIXR_RX_OVF)
dev_warn(drvdata->serio.dev.parent, "receive overrun error\n");
dev_warn(drvdata->dev, "receive overrun error\n");
if (intr_sr & XPS2_IPIXR_RX_ERR)
drvdata->flags |= SERIO_PARITY;
......@@ -132,10 +133,10 @@ static irqreturn_t xps2_interrupt(int irq, void *dev_id)
/* Error, if a byte is not received */
if (status) {
dev_err(drvdata->serio.dev.parent,
dev_err(drvdata->dev,
"wrong rcvd byte count (%d)\n", status);
} else {
serio_interrupt(&drvdata->serio, c, drvdata->flags);
serio_interrupt(drvdata->serio, c, drvdata->flags);
drvdata->flags = 0;
}
}
......@@ -193,7 +194,7 @@ static int sxps2_open(struct serio *pserio)
error = request_irq(drvdata->irq, &xps2_interrupt, 0,
DRIVER_NAME, drvdata);
if (error) {
dev_err(drvdata->serio.dev.parent,
dev_err(drvdata->dev,
"Couldn't allocate interrupt %d\n", drvdata->irq);
return error;
}
......@@ -259,15 +260,16 @@ static int __devinit xps2_of_probe(struct platform_device *ofdev)
}
drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL);
if (!drvdata) {
dev_err(dev, "Couldn't allocate device private record\n");
return -ENOMEM;
serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!drvdata || !serio) {
error = -ENOMEM;
goto failed1;
}
dev_set_drvdata(dev, drvdata);
spin_lock_init(&drvdata->lock);
drvdata->irq = r_irq.start;
drvdata->serio = serio;
drvdata->dev = dev;
phys_addr = r_mem.start;
remap_size = resource_size(&r_mem);
......@@ -298,7 +300,6 @@ static int __devinit xps2_of_probe(struct platform_device *ofdev)
(unsigned long long)phys_addr, drvdata->base_address,
drvdata->irq);
serio = &drvdata->serio;
serio->id.type = SERIO_8042;
serio->write = sxps2_write;
serio->open = sxps2_open;
......@@ -312,13 +313,14 @@ static int __devinit xps2_of_probe(struct platform_device *ofdev)
serio_register_port(serio);
platform_set_drvdata(ofdev, drvdata);
return 0; /* success */
failed2:
release_mem_region(phys_addr, remap_size);
failed1:
kfree(serio);
kfree(drvdata);
dev_set_drvdata(dev, NULL);
return error;
}
......@@ -333,22 +335,21 @@ static int __devinit xps2_of_probe(struct platform_device *ofdev)
*/
static int __devexit xps2_of_remove(struct platform_device *of_dev)
{
struct device *dev = &of_dev->dev;
struct xps2data *drvdata = dev_get_drvdata(dev);
struct xps2data *drvdata = platform_get_drvdata(of_dev);
struct resource r_mem; /* IO mem resources */
serio_unregister_port(&drvdata->serio);
serio_unregister_port(drvdata->serio);
iounmap(drvdata->base_address);
/* Get iospace of the device */
if (of_address_to_resource(of_dev->dev.of_node, 0, &r_mem))
dev_err(dev, "invalid address\n");
dev_err(drvdata->dev, "invalid address\n");
else
release_mem_region(r_mem.start, resource_size(&r_mem));
kfree(drvdata);
dev_set_drvdata(dev, NULL);
platform_set_drvdata(of_dev, NULL);
return 0;
}
......
......@@ -1862,7 +1862,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
if (i == ARRAY_SIZE(speeds)) {
dev_info(&intf->dev,
"Aiptek tried all speeds, no sane response\n");
goto fail2;
goto fail3;
}
/* Associate this driver's struct with the usb interface.
......
......@@ -135,6 +135,6 @@ extern const struct usb_device_id wacom_ids[];
void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
void wacom_setup_device_quirks(struct wacom_features *features);
void wacom_setup_input_capabilities(struct input_dev *input_dev,
struct wacom_wac *wacom_wac);
int wacom_setup_input_capabilities(struct input_dev *input_dev,
struct wacom_wac *wacom_wac);
#endif
This diff is collapsed.
This diff is collapsed.
......@@ -25,6 +25,10 @@
#define WACOM_PKGLEN_BBTOUCH3 64
#define WACOM_PKGLEN_BBPEN 10
#define WACOM_PKGLEN_WIRELESS 32
#define WACOM_PKGLEN_MTOUCH 62
/* wacom data size per MT contact */
#define WACOM_BYTES_PER_MT_PACKET 11
/* device IDs */
#define STYLUS_DEVICE_ID 0x02
......@@ -38,8 +42,10 @@
#define WACOM_REPORT_INTUOSREAD 5
#define WACOM_REPORT_INTUOSWRITE 6
#define WACOM_REPORT_INTUOSPAD 12
#define WACOM_REPORT_INTUOS5PAD 3
#define WACOM_REPORT_TPC1FG 6
#define WACOM_REPORT_TPC2FG 13
#define WACOM_REPORT_TPCMT 13
#define WACOM_REPORT_TPCHID 15
#define WACOM_REPORT_TPCST 16
......@@ -65,6 +71,9 @@ enum {
INTUOS4S,
INTUOS4,
INTUOS4L,
INTUOS5S,
INTUOS5,
INTUOS5L,
WACOM_24HD,
WACOM_21UX2,
CINTIQ,
......@@ -72,6 +81,7 @@ enum {
WACOM_MO,
TABLETPC,
TABLETPC2FG,
MTSCREEN,
MAX_TYPE
};
......@@ -95,6 +105,7 @@ struct wacom_features {
int pressure_fuzz;
int distance_fuzz;
unsigned quirks;
unsigned touch_max;
};
struct wacom_shared {
......@@ -113,6 +124,8 @@ struct wacom_wac {
struct input_dev *input;
int pid;
int battery_capacity;
int num_contacts_left;
int *slots;
};
#endif
......@@ -187,6 +187,23 @@ config TOUCHSCREEN_DA9034
Say Y here to enable the support for the touchscreen found
on Dialog Semiconductor DA9034 PMIC.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called da9034-ts.
config TOUCHSCREEN_DA9052
tristate "Dialog DA9052/DA9053 TSI"
depends on PMIC_DA9052
help
Say Y here to support the touchscreen found on Dialog Semiconductor
DA9052-BC and DA9053-AA/Bx PMICs.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called da9052_tsi.
config TOUCHSCREEN_DYNAPRO
tristate "Dynapro serial touchscreen"
select SERIO
......@@ -306,6 +323,18 @@ config TOUCHSCREEN_WACOM_W8001
To compile this driver as a module, choose M here: the
module will be called wacom_w8001.
config TOUCHSCREEN_WACOM_I2C
tristate "Wacom Tablet support (I2C)"
depends on I2C
help
Say Y here if you want to use the I2C version of the Wacom
Pen Tablet.
If unsure, say N.
To compile this driver as a module, choose M here: the module
will be called wacom_i2c.
config TOUCHSCREEN_LPC32XX
tristate "LPC32XX touchscreen controller"
depends on ARCH_LPC32XX
......@@ -635,6 +664,7 @@ config TOUCHSCREEN_USB_COMPOSITE
- Zytronic controllers
- Elo TouchSystems 2700 IntelliTouch
- EasyTouch USB Touch Controller from Data Modul
- e2i (Mimo monitors)
Have a look at <http://linux.chapter7.ch/touchkit/> for
a usage description and the required user-space stuff.
......@@ -721,7 +751,7 @@ config TOUCHSCREEN_USB_ELO
config TOUCHSCREEN_USB_E2I
default y
bool "e2i Touchscreen controller (e.g. from Mimo 740)"
bool "e2i Touchscreen controller (e.g. from Mimo 740)" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_ZYTRONIC
......@@ -744,7 +774,7 @@ config TOUCHSCREEN_USB_EASYTOUCH
bool "EasyTouch USB Touch controller device support" if EMBEDDED
depends on TOUCHSCREEN_USB_COMPOSITE
help
Say Y here if you have a EasyTouch USB Touch controller device support.
Say Y here if you have an EasyTouch USB Touch controller.
If unsure, say N.
config TOUCHSCREEN_TOUCHIT213
......
......@@ -22,6 +22,7 @@ obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o
obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o
obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o
obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o
obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o
obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o
obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o
obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
......@@ -59,6 +60,7 @@ obj-$(CONFIG_TOUCHSCREEN_TSC2005) += tsc2005.o
obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o
obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o
obj-$(CONFIG_TOUCHSCREEN_WACOM_I2C) += wacom_i2c.o
obj-$(CONFIG_TOUCHSCREEN_WM831X) += wm831x-ts.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
......
......@@ -236,7 +236,6 @@ struct mxt_object {
struct mxt_message {
u8 reportid;
u8 message[7];
u8 checksum;
};
struct mxt_finger {
......@@ -326,17 +325,12 @@ static bool mxt_object_writable(unsigned int type)
}
static void mxt_dump_message(struct device *dev,
struct mxt_message *message)
struct mxt_message *message)
{
dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
dev_dbg(dev, "reportid: %u\tmessage: %02x %02x %02x %02x %02x %02x %02x\n",
message->reportid, message->message[0], message->message[1],
message->message[2], message->message[3], message->message[4],
message->message[5], message->message[6]);
}
static int mxt_check_bootloader(struct i2c_client *client,
......@@ -506,7 +500,7 @@ static int mxt_write_object(struct mxt_data *data,
u16 reg;
object = mxt_get_object(data, type);
if (!object)
if (!object || offset >= object->size + 1)
return -EINVAL;
reg = object->start_address;
......@@ -1049,8 +1043,8 @@ static ssize_t mxt_update_fw_store(struct device *dev,
return count;
}
static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL);
static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);
static struct attribute *mxt_attrs[] = {
&dev_attr_object.attr,
......@@ -1201,7 +1195,7 @@ static int __devexit mxt_remove(struct i2c_client *client)
return 0;
}
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static int mxt_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
......@@ -1239,13 +1233,10 @@ static int mxt_resume(struct device *dev)
return 0;
}
static const struct dev_pm_ops mxt_pm_ops = {
.suspend = mxt_suspend,
.resume = mxt_resume,
};
#endif
static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume);
static const struct i2c_device_id mxt_id[] = {
{ "qt602240_ts", 0 },
{ "atmel_mxt_ts", 0 },
......@@ -1258,9 +1249,7 @@ static struct i2c_driver mxt_driver = {
.driver = {
.name = "atmel_mxt_ts",
.owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &mxt_pm_ops,
#endif
},
.probe = mxt_probe,
.remove = __devexit_p(mxt_remove),
......
This diff is collapsed.
......@@ -188,19 +188,4 @@ static struct serio_driver dynapro_drv = {
.disconnect = dynapro_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
static int __init dynapro_init(void)
{
return serio_register_driver(&dynapro_drv);
}
static void __exit dynapro_exit(void)
{
serio_unregister_driver(&dynapro_drv);
}
module_init(dynapro_init);
module_exit(dynapro_exit);
module_serio_driver(dynapro_drv);
......@@ -405,19 +405,4 @@ static struct serio_driver elo_drv = {
.disconnect = elo_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
static int __init elo_init(void)
{
return serio_register_driver(&elo_drv);
}
static void __exit elo_exit(void)
{
serio_unregister_driver(&elo_drv);
}
module_init(elo_init);
module_exit(elo_exit);
module_serio_driver(elo_drv);
......@@ -175,15 +175,4 @@ static struct serio_driver fujitsu_drv = {
.disconnect = fujitsu_disconnect,
};
static int __init fujitsu_init(void)
{
return serio_register_driver(&fujitsu_drv);
}
static void __exit fujitsu_exit(void)
{
serio_unregister_driver(&fujitsu_drv);
}
module_init(fujitsu_init);
module_exit(fujitsu_exit);
module_serio_driver(fujitsu_drv);
......@@ -186,19 +186,4 @@ static struct serio_driver gunze_drv = {
.disconnect = gunze_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
static int __init gunze_init(void)
{
return serio_register_driver(&gunze_drv);
}
static void __exit gunze_exit(void)
{
serio_unregister_driver(&gunze_drv);
}
module_init(gunze_init);
module_exit(gunze_exit);
module_serio_driver(gunze_drv);
......@@ -476,19 +476,4 @@ static struct serio_driver h3600ts_drv = {
.disconnect = h3600ts_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
static int __init h3600ts_init(void)
{
return serio_register_driver(&h3600ts_drv);
}
static void __exit h3600ts_exit(void)
{
serio_unregister_driver(&h3600ts_drv);
}
module_init(h3600ts_init);
module_exit(h3600ts_exit);
module_serio_driver(h3600ts_drv);
......@@ -187,19 +187,4 @@ static struct serio_driver hampshire_drv = {
.disconnect = hampshire_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
static int __init hampshire_init(void)
{
return serio_register_driver(&hampshire_drv);
}
static void __exit hampshire_exit(void)
{
serio_unregister_driver(&hampshire_drv);
}
module_init(hampshire_init);
module_exit(hampshire_exit);
module_serio_driver(hampshire_drv);
......@@ -189,19 +189,4 @@ static struct serio_driver inexio_drv = {
.disconnect = inexio_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
static int __init inexio_init(void)
{
return serio_register_driver(&inexio_drv);
}
static void __exit inexio_exit(void)
{
serio_unregister_driver(&inexio_drv);
}
module_init(inexio_init);
module_exit(inexio_exit);
module_serio_driver(inexio_drv);
......@@ -22,6 +22,7 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/of.h>
/*
* Touchscreen controller register offsets
......@@ -383,6 +384,14 @@ static const struct dev_pm_ops lpc32xx_ts_pm_ops = {
#define LPC32XX_TS_PM_OPS NULL
#endif
#ifdef CONFIG_OF
static struct of_device_id lpc32xx_tsc_of_match[] = {
{ .compatible = "nxp,lpc3220-tsc", },
{ },
};
MODULE_DEVICE_TABLE(of, lpc32xx_tsc_of_match);
#endif
static struct platform_driver lpc32xx_ts_driver = {
.probe = lpc32xx_ts_probe,
.remove = __devexit_p(lpc32xx_ts_remove),
......@@ -390,6 +399,7 @@ static struct platform_driver lpc32xx_ts_driver = {
.name = MOD_NAME,
.owner = THIS_MODULE,
.pm = LPC32XX_TS_PM_OPS,
.of_match_table = of_match_ptr(lpc32xx_tsc_of_match),
},
};
module_platform_driver(lpc32xx_ts_driver);
......
......@@ -202,19 +202,4 @@ static struct serio_driver mtouch_drv = {
.disconnect = mtouch_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
static int __init mtouch_init(void)
{
return serio_register_driver(&mtouch_drv);
}
static void __exit mtouch_exit(void)
{
serio_unregister_driver(&mtouch_drv);
}
module_init(mtouch_init);
module_exit(mtouch_exit);
module_serio_driver(mtouch_drv);
......@@ -317,19 +317,4 @@ static struct serio_driver pm_drv = {
.disconnect = pm_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
static int __init pm_init(void)
{
return serio_register_driver(&pm_drv);
}
static void __exit pm_exit(void)
{
serio_unregister_driver(&pm_drv);
}
module_init(pm_init);
module_exit(pm_exit);
module_serio_driver(pm_drv);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -167,17 +167,7 @@ static struct serio_driver tsc_drv = {
.disconnect = tsc_disconnect,
};
static int __init tsc_ser_init(void)
{
return serio_register_driver(&tsc_drv);
}
module_init(tsc_ser_init);
static void __exit tsc_exit(void)
{
serio_unregister_driver(&tsc_drv);
}
module_exit(tsc_exit);
module_serio_driver(tsc_drv);
MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
MODULE_DESCRIPTION(DRIVER_DESC);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment