Commit 7bfe0e66 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 subsystem updates from Dmitry Torokhov:
 "- we finally merged driver for USB version of Synaptics touchpads
    (I guess most commonly found in IBM/Lenovo keyboard/touchpad combo);

   - a bunch of new drivers for embedded platforms (Cypress
     touchscreens, DA9052 OnKey, MAX8997-haptic, Ilitek ILI210x
     touchscreens, TI touchscreen);

   - input core allows clients to specify desired clock source for
     timestamps on input events (EVIOCSCLOCKID ioctl);

   - input core allows querying state of all MT slots for given event
     code via EVIOCGMTSLOTS ioctl;

   - various driver fixes and improvements."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (45 commits)
  Input: ili210x - add support for Ilitek ILI210x based touchscreens
  Input: altera_ps2 - use of_match_ptr()
  Input: synaptics_usb - switch to module_usb_driver()
  Input: convert I2C drivers to use module_i2c_driver()
  Input: convert SPI drivers to use module_spi_driver()
  Input: omap4-keypad - move platform_data to <linux/platform_data>
  Input: kxtj9 - who_am_i check value and initial data rate fixes
  Input: add driver support for MAX8997-haptic
  Input: tegra-kbc - revise device tree support
  Input: of_keymap - add device tree bindings for simple key matrices
  Input: wacom - fix physical size calculation for 3rd-gen Bamboo
  Input: twl4030-vibra - really switch from #if to #ifdef
  Input: hp680_ts_input - ensure arguments to request_irq and free_irq are compatible
  Input: max8925_onkey - avoid accessing input device too early
  Input: max8925_onkey - allow to be used as a wakeup source
  Input: atmel-wm97xx - convert to dev_pm_ops
  Input: atmel-wm97xx - set driver owner
  Input: add cyttsp touchscreen maintainer entry
  Input: cyttsp - remove useless checks in cyttsp_probe()
  Input: usbtouchscreen - add support for Data Modul EasyTouch TP 72037
  ...
parents 6a76a699 10ce3cc9
A simple common binding for matrix-connected key boards. Currently targeted at
defining the keys in the scope of linux key codes since that is a stable and
standardized interface at this time.
Required properties:
- linux,keymap: an array of packed 1-cell entries containing the equivalent
of row, column and linux key-code. The 32-bit big endian cell is packed
as:
row << 24 | column << 16 | key-code
Optional properties:
Some users of this binding might choose to specify secondary keymaps for
cases where there is a modifier key such as a Fn key. Proposed names
for said properties are "linux,fn-keymap" or with another descriptive
word for the modifier other from "Fn".
Example:
linux,keymap = < 0x00030012
0x0102003a >;
......@@ -3,16 +3,21 @@
Required properties:
- compatible: "nvidia,tegra20-kbc"
Optional properties:
- debounce-delay: delay in milliseconds per row scan for debouncing
- repeat-delay: delay in milliseconds before repeat starts
- ghost-filter: enable ghost filtering for this device
- wakeup-source: configure keyboard as a wakeup source for suspend/resume
Optional properties, in addition to those specified by the shared
matrix-keyboard bindings:
- linux,fn-keymap: a second keymap, same specification as the
matrix-keyboard-controller spec but to be used when the KEY_FN modifier
key is pressed.
- nvidia,debounce-delay-ms: delay in milliseconds per row scan for debouncing
- nvidia,repeat-delay-ms: delay in milliseconds before repeat starts
- nvidia,ghost-filter: enable ghost filtering for this device
- nvidia,wakeup-source: configure keyboard as a wakeup source for suspend/resume
Example:
keyboard: keyboard {
compatible = "nvidia,tegra20-kbc";
reg = <0x7000e200 0x100>;
ghost-filter;
nvidia,ghost-filter;
};
......@@ -2109,6 +2109,13 @@ W: http://www.cyclades.com/
S: Orphan
F: drivers/net/wan/pc300*
CYTTSP TOUCHSCREEN DRIVER
M: Javier Martinez Canillas <javier@dowhile0.org>
L: linux-input@vger.kernel.org
S: Maintained
F: drivers/input/touchscreen/cyttsp*
F: include/linux/input/cyttsp.h
DAMA SLAVE for AX.25
M: Joerg Reuter <jreuter@yaina.de>
W: http://yaina.de/jreuter/
......
......@@ -25,6 +25,7 @@
#include <linux/regulator/fixed.h>
#include <linux/leds.h>
#include <linux/leds_pwm.h>
#include <linux/platform_data/omap4-keypad.h>
#include <mach/hardware.h>
#include <asm/hardware/gic.h>
......
......@@ -17,6 +17,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/platform_data/omap4-keypad.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
......
......@@ -24,20 +24,21 @@
#include <linux/types.h>
#include <linux/input/matrix_keypad.h>
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
#define KBC_MAX_GPIO 24
#define KBC_MAX_KPENT 8
#else
#define KBC_MAX_GPIO 20
#define KBC_MAX_KPENT 7
#endif
#define KBC_MAX_ROW 16
#define KBC_MAX_COL 8
#define KBC_MAX_KEY (KBC_MAX_ROW * KBC_MAX_COL)
enum tegra_pin_type {
PIN_CFG_IGNORE,
PIN_CFG_COL,
PIN_CFG_ROW,
};
struct tegra_kbc_pin_cfg {
bool is_row;
enum tegra_pin_type type;
unsigned char num;
};
......
#ifndef ARCH_ARM_PLAT_OMAP4_KEYPAD_H
#define ARCH_ARM_PLAT_OMAP4_KEYPAD_H
#include <linux/input/matrix_keypad.h>
struct omap4_keypad_platform_data {
const struct matrix_keymap_data *keymap_data;
u8 rows;
u8 cols;
};
extern int omap4_keyboard_init(struct omap4_keypad_platform_data *,
struct omap_board_data *);
#endif
......@@ -15,7 +15,7 @@
#include <linux/input/matrix_keypad.h>
#include <linux/types.h>
#define DECLARE_KEYMAP(_name) \
#define DECLARE_9x9_KEYMAP(_name) \
int _name[] = { \
KEY(0, 0, KEY_ESC), \
KEY(0, 1, KEY_1), \
......@@ -62,24 +62,6 @@ int _name[] = { \
KEY(4, 6, KEY_Z), \
KEY(4, 7, KEY_X), \
KEY(4, 8, KEY_C), \
KEY(4, 0, KEY_L), \
KEY(4, 1, KEY_SEMICOLON), \
KEY(4, 2, KEY_APOSTROPHE), \
KEY(4, 3, KEY_GRAVE), \
KEY(4, 4, KEY_LEFTSHIFT), \
KEY(4, 5, KEY_BACKSLASH), \
KEY(4, 6, KEY_Z), \
KEY(4, 7, KEY_X), \
KEY(4, 8, KEY_C), \
KEY(4, 0, KEY_L), \
KEY(4, 1, KEY_SEMICOLON), \
KEY(4, 2, KEY_APOSTROPHE), \
KEY(4, 3, KEY_GRAVE), \
KEY(4, 4, KEY_LEFTSHIFT), \
KEY(4, 5, KEY_BACKSLASH), \
KEY(4, 6, KEY_Z), \
KEY(4, 7, KEY_X), \
KEY(4, 8, KEY_C), \
KEY(5, 0, KEY_V), \
KEY(5, 1, KEY_B), \
KEY(5, 2, KEY_N), \
......@@ -118,10 +100,55 @@ int _name[] = { \
KEY(8, 8, KEY_KP0), \
}
#define DECLARE_6x6_KEYMAP(_name) \
int _name[] = { \
KEY(0, 0, KEY_RESERVED), \
KEY(0, 1, KEY_1), \
KEY(0, 2, KEY_2), \
KEY(0, 3, KEY_3), \
KEY(0, 4, KEY_4), \
KEY(0, 5, KEY_5), \
KEY(1, 0, KEY_Q), \
KEY(1, 1, KEY_W), \
KEY(1, 2, KEY_E), \
KEY(1, 3, KEY_R), \
KEY(1, 4, KEY_T), \
KEY(1, 5, KEY_Y), \
KEY(2, 0, KEY_D), \
KEY(2, 1, KEY_F), \
KEY(2, 2, KEY_G), \
KEY(2, 3, KEY_H), \
KEY(2, 4, KEY_J), \
KEY(2, 5, KEY_K), \
KEY(3, 0, KEY_B), \
KEY(3, 1, KEY_N), \
KEY(3, 2, KEY_M), \
KEY(3, 3, KEY_COMMA), \
KEY(3, 4, KEY_DOT), \
KEY(3, 5, KEY_SLASH), \
KEY(4, 0, KEY_F6), \
KEY(4, 1, KEY_F7), \
KEY(4, 2, KEY_F8), \
KEY(4, 3, KEY_F9), \
KEY(4, 4, KEY_F10), \
KEY(4, 5, KEY_NUMLOCK), \
KEY(5, 0, KEY_KP2), \
KEY(5, 1, KEY_KP3), \
KEY(5, 2, KEY_KP0), \
KEY(5, 3, KEY_KPDOT), \
KEY(5, 4, KEY_RO), \
KEY(5, 5, KEY_ZENKAKUHANKAKU), \
}
#define KEYPAD_9x9 0
#define KEYPAD_6x6 1
#define KEYPAD_2x2 2
/**
* struct kbd_platform_data - spear keyboard platform data
* keymap: pointer to keymap data (table and size)
* rep: enables key autorepeat
* mode: choose keyboard support(9x9, 6x6, 2x2)
*
* This structure is supposed to be used by platform code to supply
* keymaps to drivers that implement keyboards.
......@@ -129,6 +156,7 @@ int _name[] = { \
struct kbd_platform_data {
const struct matrix_keymap_data *keymap;
bool rep;
unsigned int mode;
};
/* This function is used to set platform data field of pdev->dev */
......
......@@ -24,6 +24,7 @@
#include <linux/rtc.h>
#include <linux/vt_kern.h>
#include <linux/bcd.h>
#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/rtc.h>
......@@ -329,3 +330,15 @@ static int q40_set_rtc_pll(struct rtc_pll_info *pll)
} else
return -EINVAL;
}
static __init int q40_add_kbd_device(void)
{
struct platform_device *pdev;
pdev = platform_device_register_simple("q40kbd", -1, NULL, 0);
if (IS_ERR(pdev))
return PTR_ERR(pdev);
return 0;
}
arch_initcall(q40_add_kbd_device);
......@@ -1935,6 +1935,16 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) },
#if defined(CONFIG_MOUSE_SYNAPTICS_USB) || defined(CONFIG_MOUSE_SYNAPTICS_USB_MODULE)
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_INT_TP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_CPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_STICK) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_WP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_COMP_TP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_WTP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DPAD) },
#endif
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
......
......@@ -677,6 +677,17 @@
#define USB_DEVICE_ID_SYMBOL_SCANNER_1 0x0800
#define USB_DEVICE_ID_SYMBOL_SCANNER_2 0x1300
#define USB_VENDOR_ID_SYNAPTICS 0x06cb
#define USB_DEVICE_ID_SYNAPTICS_TP 0x0001
#define USB_DEVICE_ID_SYNAPTICS_INT_TP 0x0002
#define USB_DEVICE_ID_SYNAPTICS_CPAD 0x0003
#define USB_DEVICE_ID_SYNAPTICS_TS 0x0006
#define USB_DEVICE_ID_SYNAPTICS_STICK 0x0007
#define USB_DEVICE_ID_SYNAPTICS_WP 0x0008
#define USB_DEVICE_ID_SYNAPTICS_COMP_TP 0x0009
#define USB_DEVICE_ID_SYNAPTICS_WTP 0x0010
#define USB_DEVICE_ID_SYNAPTICS_DPAD 0x0013
#define USB_VENDOR_ID_THRUSTMASTER 0x044f
#define USB_VENDOR_ID_TIVO 0x150a
......
......@@ -25,6 +25,10 @@ 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
......
......@@ -24,3 +24,4 @@ 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
......@@ -20,7 +20,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/major.h>
#include <linux/device.h>
#include "input-compat.h"
......@@ -46,6 +46,7 @@ struct evdev_client {
struct fasync_struct *fasync;
struct evdev *evdev;
struct list_head node;
int clkid;
unsigned int bufsize;
struct input_event buffer[];
};
......@@ -54,8 +55,12 @@ static struct evdev *evdev_table[EVDEV_MINORS];
static DEFINE_MUTEX(evdev_table_mutex);
static void evdev_pass_event(struct evdev_client *client,
struct input_event *event)
struct input_event *event,
ktime_t mono, ktime_t real)
{
event->time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
mono : real);
/* Interrupts are disabled, just acquire the lock. */
spin_lock(&client->buffer_lock);
......@@ -94,8 +99,11 @@ static void evdev_event(struct input_handle *handle,
struct evdev *evdev = handle->private;
struct evdev_client *client;
struct input_event event;
ktime_t time_mono, time_real;
time_mono = ktime_get();
time_real = ktime_sub(time_mono, ktime_get_monotonic_offset());
do_gettimeofday(&event.time);
event.type = type;
event.code = code;
event.value = value;
......@@ -103,11 +111,12 @@ static void evdev_event(struct input_handle *handle,
rcu_read_lock();
client = rcu_dereference(evdev->grab);
if (client)
evdev_pass_event(client, &event);
evdev_pass_event(client, &event, time_mono, time_real);
else
list_for_each_entry_rcu(client, &evdev->client_list, node)
evdev_pass_event(client, &event);
evdev_pass_event(client, &event, time_mono, time_real);
rcu_read_unlock();
......@@ -623,6 +632,28 @@ static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p)
return input_set_keycode(dev, &ke);
}
static int evdev_handle_mt_request(struct input_dev *dev,
unsigned int size,
int __user *ip)
{
const struct input_mt_slot *mt = dev->mt;
unsigned int code;
int max_slots;
int i;
if (get_user(code, &ip[0]))
return -EFAULT;
if (!input_is_mt_value(code))
return -EINVAL;
max_slots = (size - sizeof(__u32)) / sizeof(__s32);
for (i = 0; i < dev->mtsize && i < max_slots; i++)
if (put_user(input_mt_get_value(&mt[i], code), &ip[1 + i]))
return -EFAULT;
return 0;
}
static long evdev_do_ioctl(struct file *file, unsigned int cmd,
void __user *p, int compat_mode)
{
......@@ -685,6 +716,14 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
else
return evdev_ungrab(evdev, client);
case EVIOCSCLOCKID:
if (copy_from_user(&i, p, sizeof(unsigned int)))
return -EFAULT;
if (i != CLOCK_MONOTONIC && i != CLOCK_REALTIME)
return -EINVAL;
client->clkid = i;
return 0;
case EVIOCGKEYCODE:
return evdev_handle_get_keycode(dev, p);
......@@ -708,6 +747,9 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
return bits_to_user(dev->propbit, INPUT_PROP_MAX,
size, p, compat_mode);
case EVIOCGMTSLOTS(0):
return evdev_handle_mt_request(dev, size, ip);
case EVIOCGKEY(0):
return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode);
......
......@@ -180,7 +180,7 @@ static int input_handle_abs_event(struct input_dev *dev,
return INPUT_IGNORE_EVENT;
}
is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST;
is_mt_event = input_is_mt_value(code);
if (!is_mt_event) {
pold = &dev->absinfo[code].value;
......
......@@ -355,14 +355,4 @@ static struct i2c_driver as5011_driver = {
.id_table = as5011_id,
};
static int __init as5011_init(void)
{
return i2c_add_driver(&as5011_driver);
}
module_init(as5011_init);
static void __exit as5011_exit(void)
{
i2c_del_driver(&as5011_driver);
}
module_exit(as5011_exit);
module_i2c_driver(as5011_driver);
......@@ -394,6 +394,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
help
Say Y here if you want to use a matrix keyboard connected directly
to the internal keyboard controller on Tegra SoCs.
......@@ -512,7 +513,6 @@ config KEYBOARD_OMAP
config KEYBOARD_OMAP4
tristate "TI OMAP4 keypad support"
depends on ARCH_OMAP4
help
Say Y here if you want to use the OMAP4 keypad.
......
......@@ -653,17 +653,7 @@ static struct i2c_driver adp5588_driver = {
.id_table = adp5588_id,
};
static int __init adp5588_init(void)
{
return i2c_add_driver(&adp5588_driver);
}
module_init(adp5588_init);
static void __exit adp5588_exit(void)
{
i2c_del_driver(&adp5588_driver);
}
module_exit(adp5588_exit);
module_i2c_driver(adp5588_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
......
......@@ -1108,17 +1108,7 @@ static struct i2c_driver adp5589_driver = {
.id_table = adp5589_id,
};
static int __init adp5589_init(void)
{
return i2c_add_driver(&adp5589_driver);
}
module_init(adp5589_init);
static void __exit adp5589_exit(void)
{
i2c_del_driver(&adp5589_driver);
}
module_exit(adp5589_exit);
module_i2c_driver(adp5589_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
......
......@@ -851,17 +851,7 @@ static struct i2c_driver lm8323_i2c_driver = {
};
MODULE_DEVICE_TABLE(i2c, lm8323_id);
static int __init lm8323_init(void)
{
return i2c_add_driver(&lm8323_i2c_driver);
}
module_init(lm8323_init);
static void __exit lm8323_exit(void)
{
i2c_del_driver(&lm8323_i2c_driver);
}
module_exit(lm8323_exit);
module_i2c_driver(lm8323_i2c_driver);
MODULE_AUTHOR("Timo O. Karjalainen <timo.o.karjalainen@nokia.com>");
MODULE_AUTHOR("Daniel Stone");
......
......@@ -316,17 +316,7 @@ static struct i2c_driver max7359_i2c_driver = {
.id_table = max7359_ids,
};
static int __init max7359_init(void)
{
return i2c_add_driver(&max7359_i2c_driver);
}
module_init(max7359_init);
static void __exit max7359_exit(void)
{
i2c_del_driver(&max7359_i2c_driver);
}
module_exit(max7359_exit);
module_i2c_driver(max7359_i2c_driver);
MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>");
MODULE_DESCRIPTION("MAX7359 Key Switch Controller Driver");
......
......@@ -274,18 +274,7 @@ static struct i2c_driver mcs_touchkey_driver = {
.id_table = mcs_touchkey_id,
};
static int __init mcs_touchkey_init(void)
{
return i2c_add_driver(&mcs_touchkey_driver);
}
static void __exit mcs_touchkey_exit(void)
{
i2c_del_driver(&mcs_touchkey_driver);
}
module_init(mcs_touchkey_init);
module_exit(mcs_touchkey_exit);
module_i2c_driver(mcs_touchkey_driver);
/* Module information */
MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
......
......@@ -330,17 +330,7 @@ static struct i2c_driver mpr_touchkey_driver = {
.remove = __devexit_p(mpr_touchkey_remove),
};
static int __init mpr_touchkey_init(void)
{
return i2c_add_driver(&mpr_touchkey_driver);
}
module_init(mpr_touchkey_init);
static void __exit mpr_touchkey_exit(void)
{
i2c_del_driver(&mpr_touchkey_driver);
}
module_exit(mpr_touchkey_exit);
module_i2c_driver(mpr_touchkey_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Zhang Jiejing <jiejing.zhang@freescale.com>");
......
......@@ -88,7 +88,7 @@ static void ske_keypad_set_bits(struct ske_keypad *keypad, u16 addr,
*
* Enable Multi key press detection, auto scan mode
*/
static int __devinit ske_keypad_chip_init(struct ske_keypad *keypad)
static int __init ske_keypad_chip_init(struct ske_keypad *keypad)
{
u32 value;
int timeout = 50;
......@@ -198,7 +198,7 @@ static irqreturn_t ske_keypad_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
static int __devinit ske_keypad_probe(struct platform_device *pdev)
static int __init ske_keypad_probe(struct platform_device *pdev)
{
const struct ske_keypad_platform_data *plat = pdev->dev.platform_data;
struct ske_keypad *keypad;
......@@ -344,7 +344,7 @@ static int __devexit ske_keypad_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static int ske_keypad_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
......@@ -372,22 +372,17 @@ static int ske_keypad_resume(struct device *dev)
return 0;
}
static const struct dev_pm_ops ske_keypad_dev_pm_ops = {
.suspend = ske_keypad_suspend,
.resume = ske_keypad_resume,
};
#endif
static SIMPLE_DEV_PM_OPS(ske_keypad_dev_pm_ops,
ske_keypad_suspend, ske_keypad_resume);
static struct platform_driver ske_keypad_driver = {
.driver = {
.name = "nmk-ske-keypad",
.owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &ske_keypad_dev_pm_ops,
#endif
},
.probe = ske_keypad_probe,
.remove = __devexit_p(ske_keypad_remove),
};
......
......@@ -31,7 +31,7 @@
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <plat/omap4-keypad.h>
#include <linux/platform_data/omap4-keypad.h>
/* OMAP4 registers */
#define OMAP4_KBD_REVISION 0x00
......
......@@ -258,17 +258,7 @@ static struct i2c_driver qt1070_driver = {
.remove = __devexit_p(qt1070_remove),
};
static int __init qt1070_init(void)
{
return i2c_add_driver(&qt1070_driver);
}
module_init(qt1070_init);
static void __exit qt1070_exit(void)
{
i2c_del_driver(&qt1070_driver);
}
module_exit(qt1070_exit);
module_i2c_driver(qt1070_driver);
MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>");
MODULE_DESCRIPTION("Driver for AT42QT1070 QTouch sensor");
......
......@@ -379,17 +379,7 @@ static struct i2c_driver qt2160_driver = {
.remove = __devexit_p(qt2160_remove),
};
static int __init qt2160_init(void)
{
return i2c_add_driver(&qt2160_driver);
}
module_init(qt2160_init);
static void __exit qt2160_cleanup(void)
{
i2c_del_driver(&qt2160_driver);
}
module_exit(qt2160_cleanup);
module_i2c_driver(qt2160_driver);
MODULE_AUTHOR("Raphael Derosso Pereira <raphaelpereira@gmail.com>");
MODULE_DESCRIPTION("Driver for AT42QT2160 Touch Sensor");
......
......@@ -175,7 +175,7 @@ static irqreturn_t samsung_keypad_irq(int irq, void *dev_id)
} while (key_down && !keypad->stopped);
pm_runtime_put_sync(&keypad->pdev->dev);
pm_runtime_put(&keypad->pdev->dev);
return IRQ_HANDLED;
}
......@@ -199,7 +199,7 @@ static void samsung_keypad_start(struct samsung_keypad *keypad)
/* KEYIFCOL reg clear. */
writel(0, keypad->base + SAMSUNG_KEYIFCOL);
pm_runtime_put_sync(&keypad->pdev->dev);
pm_runtime_put(&keypad->pdev->dev);
}
static void samsung_keypad_stop(struct samsung_keypad *keypad)
......@@ -229,7 +229,7 @@ static void samsung_keypad_stop(struct samsung_keypad *keypad)
*/
enable_irq(keypad->irq);
pm_runtime_put_sync(&keypad->pdev->dev);
pm_runtime_put(&keypad->pdev->dev);
}
static int samsung_keypad_open(struct input_dev *input_dev)
......
......@@ -50,6 +50,7 @@
#define ROW_MASK 0xF0
#define COLUMN_MASK 0x0F
#define ROW_SHIFT 4
#define KEY_MATRIX_SHIFT 6
struct spear_kbd {
struct input_dev *input;
......@@ -57,6 +58,7 @@ struct spear_kbd {
void __iomem *io_base;
struct clk *clk;
unsigned int irq;
unsigned int mode;
unsigned short last_key;
unsigned short keycodes[256];
};
......@@ -106,7 +108,8 @@ static int spear_kbd_open(struct input_dev *dev)
return error;
/* program keyboard */
val = SCAN_RATE_80 | MODE_KEYBOARD | PCLK_FREQ_MSK;
val = SCAN_RATE_80 | MODE_KEYBOARD | PCLK_FREQ_MSK |
(kbd->mode << KEY_MATRIX_SHIFT);
writew(val, kbd->io_base + MODE_REG);
writeb(1, kbd->io_base + STATUS_REG);
......@@ -176,6 +179,8 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev)
kbd->input = input_dev;
kbd->irq = irq;
kbd->mode = pdata->mode;
kbd->res = request_mem_region(res->start, resource_size(res),
pdev->name);
if (!kbd->res) {
......@@ -308,22 +313,17 @@ static int spear_kbd_resume(struct device *dev)
return 0;
}
static const struct dev_pm_ops spear_kbd_pm_ops = {
.suspend = spear_kbd_suspend,
.resume = spear_kbd_resume,
};
#endif
static SIMPLE_DEV_PM_OPS(spear_kbd_pm_ops, spear_kbd_suspend, spear_kbd_resume);
static struct platform_driver spear_kbd_driver = {
.probe = spear_kbd_probe,
.remove = __devexit_p(spear_kbd_remove),
.driver = {
.name = "keyboard",
.owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &spear_kbd_pm_ops,
#endif
},
};
module_platform_driver(spear_kbd_driver);
......
......@@ -48,6 +48,7 @@
#define KBC_FIFO_TH_CNT_SHIFT(cnt) (cnt << 14)
#define KBC_DEBOUNCE_CNT_SHIFT(cnt) (cnt << 4)
#define KBC_CONTROL_FIFO_CNT_INT_EN (1 << 3)
#define KBC_CONTROL_KEYPRESS_INT_EN (1 << 1)
#define KBC_CONTROL_KBC_EN (1 << 0)
/* KBC Interrupt Register */
......@@ -356,6 +357,18 @@ static void tegra_kbc_set_fifo_interrupt(struct tegra_kbc *kbc, bool enable)
writel(val, kbc->mmio + KBC_CONTROL_0);
}
static void tegra_kbc_set_keypress_interrupt(struct tegra_kbc *kbc, bool enable)
{
u32 val;
val = readl(kbc->mmio + KBC_CONTROL_0);
if (enable)
val |= KBC_CONTROL_KEYPRESS_INT_EN;
else
val &= ~KBC_CONTROL_KEYPRESS_INT_EN;
writel(val, kbc->mmio + KBC_CONTROL_0);
}
static void tegra_kbc_keypress_timer(unsigned long data)
{
struct tegra_kbc *kbc = (struct tegra_kbc *)data;
......@@ -455,10 +468,18 @@ static void tegra_kbc_config_pins(struct tegra_kbc *kbc)
row_cfg &= ~r_mask;
col_cfg &= ~c_mask;
if (pdata->pin_cfg[i].is_row)
switch (pdata->pin_cfg[i].type) {
case PIN_CFG_ROW:
row_cfg |= ((pdata->pin_cfg[i].num << 1) | 1) << r_shft;
else
break;
case PIN_CFG_COL:
col_cfg |= ((pdata->pin_cfg[i].num << 1) | 1) << c_shft;
break;
case PIN_CFG_IGNORE:
break;
}
writel(row_cfg, kbc->mmio + r_offs);
writel(col_cfg, kbc->mmio + c_offs);
......@@ -563,7 +584,8 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata,
for (i = 0; i < KBC_MAX_GPIO; i++) {
const struct tegra_kbc_pin_cfg *pin_cfg = &pdata->pin_cfg[i];
if (pin_cfg->is_row) {
switch (pin_cfg->type) {
case PIN_CFG_ROW:
if (pin_cfg->num >= KBC_MAX_ROW) {
dev_err(dev,
"pin_cfg[%d]: invalid row number %d\n",
......@@ -571,13 +593,25 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata,
return false;
}
(*num_rows)++;
} else {
break;
case PIN_CFG_COL:
if (pin_cfg->num >= KBC_MAX_COL) {
dev_err(dev,
"pin_cfg[%d]: invalid column number %d\n",
i, pin_cfg->num);
return false;
}
break;
case PIN_CFG_IGNORE:
break;
default:
dev_err(dev,
"pin_cfg[%d]: invalid entry type %d\n",
pin_cfg->type, pin_cfg->num);
return false;
}
}
......@@ -590,24 +624,25 @@ tegra_kbc_dt_parse_pdata(struct platform_device *pdev)
{
struct tegra_kbc_platform_data *pdata;
struct device_node *np = pdev->dev.of_node;
u32 prop;
int i;
if (!np)
return NULL;
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return NULL;
if (!of_property_read_u32(np, "debounce-delay", &prop))
if (!of_property_read_u32(np, "nvidia,debounce-delay-ms", &prop))
pdata->debounce_cnt = prop;
if (!of_property_read_u32(np, "repeat-delay", &prop))
if (!of_property_read_u32(np, "nvidia,repeat-delay-ms", &prop))
pdata->repeat_cnt = prop;
if (of_find_property(np, "needs-ghost-filter", NULL))
if (of_find_property(np, "nvidia,needs-ghost-filter", NULL))
pdata->use_ghost_filter = true;
if (of_find_property(np, "wakeup-source", NULL))
if (of_find_property(np, "nvidia,wakeup-source", NULL))
pdata->wakeup = true;
/*
......@@ -616,14 +651,18 @@ tegra_kbc_dt_parse_pdata(struct platform_device *pdev)
*/
for (i = 0; i < KBC_MAX_ROW; i++) {
pdata->pin_cfg[i].num = i;
pdata->pin_cfg[i].is_row = true;
pdata->pin_cfg[i].type = PIN_CFG_ROW;
}
for (i = 0; i < KBC_MAX_COL; i++) {
pdata->pin_cfg[KBC_MAX_ROW + i].num = i;
pdata->pin_cfg[KBC_MAX_ROW + i].is_row = false;
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
......@@ -759,6 +798,9 @@ 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:
......@@ -773,8 +815,10 @@ 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)
if (!pdev->dev.platform_data) {
matrix_keyboard_of_free_keymap(pdata->keymap_data);
kfree(pdata);
}
return err;
}
......@@ -831,6 +875,8 @@ static int tegra_kbc_suspend(struct device *dev)
msleep(30);
kbc->keypress_caused_wake = false;
/* Enable keypress interrupt before going into suspend. */
tegra_kbc_set_keypress_interrupt(kbc, true);
enable_irq(kbc->irq);
enable_irq_wake(kbc->irq);
} else {
......@@ -852,6 +898,8 @@ static int tegra_kbc_resume(struct device *dev)
if (device_may_wakeup(&pdev->dev)) {
disable_irq_wake(kbc->irq);
tegra_kbc_setup_wakekeys(kbc, false);
/* We will use fifo interrupts for key detection. */
tegra_kbc_set_keypress_interrupt(kbc, false);
/* Restore the resident time of continuous polling mode. */
writel(kbc->cp_to_wkup_dly, kbc->mmio + KBC_TO_CNT_0);
......
......@@ -134,6 +134,18 @@ config INPUT_MAX8925_ONKEY
To compile this driver as a module, choose M here: the module
will be called max8925_onkey.
config INPUT_MAX8997_HAPTIC
tristate "MAXIM MAX8997 haptic controller support"
depends on HAVE_PWM && MFD_MAX8997
select INPUT_FF_MEMLESS
help
This option enables device driver support for the haptic controller
on MAXIM MAX8997 chip. This driver supports ff-memless interface
from input framework.
To compile this driver as module, choose M here: the
module will be called max8997-haptic.
config INPUT_MC13783_PWRBUTTON
tristate "MC13783 ON buttons"
depends on MFD_MC13783
......@@ -415,7 +427,7 @@ config INPUT_PCF8574
tristate "PCF8574 Keypad input device"
depends on I2C && EXPERIMENTAL
help
Say Y here if you want to support a keypad connetced via I2C
Say Y here if you want to support a keypad connected via I2C
with a PCF8574.
To compile this driver as a module, choose M here: the
......@@ -455,6 +467,16 @@ config INPUT_RB532_BUTTON
To compile this driver as a module, choose M here: the
module will be called rb532_button.
config INPUT_DA9052_ONKEY
tristate "Dialog DA9052/DA9053 Onkey"
depends on PMIC_DA9052
help
Support the ONKEY of Dialog DA9052 PMICs as an input device
reporting power button status.
To compile this driver as a module, choose M here: the
module will be called da9052_onkey.
config INPUT_DM355EVM
tristate "TI DaVinci DM355 EVM Keypad and IR Remote"
depends on MFD_DM355EVM_MSP
......
......@@ -21,6 +21,7 @@ obj-$(CONFIG_INPUT_CM109) += cm109.o
obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o
obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o
obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o
obj-$(CONFIG_INPUT_DA9052_ONKEY) += da9052_onkey.o
obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o
obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o
obj-$(CONFIG_INPUT_GPIO_TILT_POLLED) += gpio_tilt_polled.o
......@@ -30,6 +31,7 @@ obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o
obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o
obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o
obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o
obj-$(CONFIG_INPUT_MMA8450) += mma8450.o
obj-$(CONFIG_INPUT_MPU3050) += mpu3050.o
......
......@@ -116,17 +116,7 @@ static struct i2c_driver ad714x_i2c_driver = {
.id_table = ad714x_id,
};
static int __init ad714x_i2c_init(void)
{
return i2c_add_driver(&ad714x_i2c_driver);
}
module_init(ad714x_i2c_init);
static void __exit ad714x_i2c_exit(void)
{
i2c_del_driver(&ad714x_i2c_driver);
}
module_exit(ad714x_i2c_exit);
module_i2c_driver(ad714x_i2c_driver);
MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor I2C Bus Driver");
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
......
......@@ -123,17 +123,7 @@ static struct spi_driver ad714x_spi_driver = {
.remove = __devexit_p(ad714x_spi_remove),
};
static __init int ad714x_spi_init(void)
{
return spi_register_driver(&ad714x_spi_driver);
}
module_init(ad714x_spi_init);
static __exit void ad714x_spi_exit(void)
{
spi_unregister_driver(&ad714x_spi_driver);
}
module_exit(ad714x_spi_exit);
module_spi_driver(ad714x_spi_driver);
MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor SPI Bus Driver");
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
......
......@@ -148,17 +148,7 @@ static struct i2c_driver adxl34x_driver = {
.id_table = adxl34x_id,
};
static int __init adxl34x_i2c_init(void)
{
return i2c_add_driver(&adxl34x_driver);
}
module_init(adxl34x_i2c_init);
static void __exit adxl34x_i2c_exit(void)
{
i2c_del_driver(&adxl34x_driver);
}
module_exit(adxl34x_i2c_exit);
module_i2c_driver(adxl34x_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer I2C Bus Driver");
......
......@@ -129,17 +129,7 @@ static struct spi_driver adxl34x_driver = {
.remove = __devexit_p(adxl34x_spi_remove),
};
static int __init adxl34x_spi_init(void)
{
return spi_register_driver(&adxl34x_driver);
}
module_init(adxl34x_spi_init);
static void __exit adxl34x_spi_exit(void)
{
spi_unregister_driver(&adxl34x_driver);
}
module_exit(adxl34x_spi_exit);
module_spi_driver(adxl34x_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer SPI Bus Driver");
......
......@@ -673,19 +673,8 @@ static struct i2c_driver bma150_driver = {
.remove = __devexit_p(bma150_remove),
};
static int __init BMA150_init(void)
{
return i2c_add_driver(&bma150_driver);
}
static void __exit BMA150_exit(void)
{
i2c_del_driver(&bma150_driver);
}
module_i2c_driver(bma150_driver);
MODULE_AUTHOR("Albert Zhang <xu.zhang@bosch-sensortec.com>");
MODULE_DESCRIPTION("BMA150 driver");
MODULE_LICENSE("GPL");
module_init(BMA150_init);
module_exit(BMA150_exit);
......@@ -125,18 +125,7 @@ static struct i2c_driver cma3000_i2c_driver = {
},
};
static int __init cma3000_i2c_init(void)
{
return i2c_add_driver(&cma3000_i2c_driver);
}
static void __exit cma3000_i2c_exit(void)
{
i2c_del_driver(&cma3000_i2c_driver);
}
module_init(cma3000_i2c_init);
module_exit(cma3000_i2c_exit);
module_i2c_driver(cma3000_i2c_driver);
MODULE_DESCRIPTION("CMA3000-D0x Accelerometer I2C Driver");
MODULE_LICENSE("GPL");
......
/*
* ON pin driver for Dialog DA9052 PMICs
*
* Copyright(c) 2012 Dialog Semiconductor Ltd.
*
* Author: David Dajun Chen <dchen@diasemi.com>
*
* 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, or (at your
* option) any later version.
*/
#include <linux/init.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/mfd/da9052/da9052.h>
#include <linux/mfd/da9052/reg.h>
struct da9052_onkey {
struct da9052 *da9052;
struct input_dev *input;
struct delayed_work work;
unsigned int irq;
};
static void da9052_onkey_query(struct da9052_onkey *onkey)
{
int key_stat;
key_stat = da9052_reg_read(onkey->da9052, DA9052_EVENT_B_REG);
if (key_stat < 0) {
dev_err(onkey->da9052->dev,
"Failed to read onkey event %d\n", key_stat);
} else {
/*
* Since interrupt for deassertion of ONKEY pin is not
* generated, onkey event state determines the onkey
* button state.
*/
key_stat &= DA9052_EVENTB_ENONKEY;
input_report_key(onkey->input, KEY_POWER, key_stat);
input_sync(onkey->input);
}
/*
* Interrupt is generated only when the ONKEY pin is asserted.
* Hence the deassertion of the pin is simulated through work queue.
*/
if (key_stat)
schedule_delayed_work(&onkey->work, msecs_to_jiffies(50));
}
static void da9052_onkey_work(struct work_struct *work)
{
struct da9052_onkey *onkey = container_of(work, struct da9052_onkey,
work.work);
da9052_onkey_query(onkey);
}
static irqreturn_t da9052_onkey_irq(int irq, void *data)
{
struct da9052_onkey *onkey = data;
da9052_onkey_query(onkey);
return IRQ_HANDLED;
}
static int __devinit da9052_onkey_probe(struct platform_device *pdev)
{
struct da9052 *da9052 = dev_get_drvdata(pdev->dev.parent);
struct da9052_onkey *onkey;
struct input_dev *input_dev;
int irq;
int error;
if (!da9052) {
dev_err(&pdev->dev, "Failed to get the driver's data\n");
return -EINVAL;
}
irq = platform_get_irq_byname(pdev, "ONKEY");
if (irq < 0) {
dev_err(&pdev->dev,
"Failed to get an IRQ for input device, %d\n", irq);
return -EINVAL;
}
onkey = kzalloc(sizeof(*onkey), GFP_KERNEL);
input_dev = input_allocate_device();
if (!onkey || !input_dev) {
dev_err(&pdev->dev, "Failed to allocate memory\n");
return -ENOMEM;
}
onkey->input = input_dev;
onkey->da9052 = da9052;
onkey->irq = irq;
INIT_DELAYED_WORK(&onkey->work, da9052_onkey_work);
input_dev->name = "da9052-onkey";
input_dev->phys = "da9052-onkey/input0";
input_dev->dev.parent = &pdev->dev;
input_dev->evbit[0] = BIT_MASK(EV_KEY);
__set_bit(KEY_POWER, input_dev->keybit);
error = request_threaded_irq(onkey->irq, NULL, da9052_onkey_irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"ONKEY", onkey);
if (error < 0) {
dev_err(onkey->da9052->dev,
"Failed to register ONKEY IRQ %d, error = %d\n",
onkey->irq, error);
goto err_free_mem;
}
error = input_register_device(onkey->input);
if (error) {
dev_err(&pdev->dev, "Unable to register input device, %d\n",
error);
goto err_free_irq;
}
platform_set_drvdata(pdev, onkey);
return 0;
err_free_irq:
free_irq(onkey->irq, onkey);
cancel_delayed_work_sync(&onkey->work);
err_free_mem:
input_free_device(input_dev);
kfree(onkey);
return error;
}
static int __devexit da9052_onkey_remove(struct platform_device *pdev)
{
struct da9052_onkey *onkey = platform_get_drvdata(pdev);
free_irq(onkey->irq, onkey);
cancel_delayed_work_sync(&onkey->work);
input_unregister_device(onkey->input);
kfree(onkey);
return 0;
}
static struct platform_driver da9052_onkey_driver = {
.probe = da9052_onkey_probe,
.remove = __devexit_p(da9052_onkey_remove),
.driver = {
.name = "da9052-onkey",
.owner = THIS_MODULE,
},
};
module_platform_driver(da9052_onkey_driver);
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
MODULE_DESCRIPTION("Onkey driver for DA9052");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:da9052-onkey");
......@@ -281,18 +281,7 @@ static struct i2c_driver gp2a_i2c_driver = {
.id_table = gp2a_i2c_id,
};
static int __init gp2a_init(void)
{
return i2c_add_driver(&gp2a_i2c_driver);
}
static void __exit gp2a_exit(void)
{
i2c_del_driver(&gp2a_i2c_driver);
}
module_init(gp2a_init);
module_exit(gp2a_exit);
module_i2c_driver(gp2a_i2c_driver);
MODULE_AUTHOR("Courtney Cavin <courtney.cavin@sonyericsson.com>");
MODULE_DESCRIPTION("Sharp GP2AP002A00F I2C Proximity/Opto sensor driver");
......
......@@ -41,6 +41,14 @@
#define PC1_ON (1 << 7)
/* Data ready funtion enable bit: set during probe if using irq mode */
#define DRDYE (1 << 5)
/* DATA CONTROL REGISTER BITS */
#define ODR12_5F 0
#define ODR25F 1
#define ODR50F 2
#define ODR100F 3
#define ODR200F 4
#define ODR400F 5
#define ODR800F 6
/* INTERRUPT CONTROL REGISTER 1 BITS */
/* Set these during probe if using irq mode */
#define KXTJ9_IEL (1 << 3)
......@@ -116,9 +124,13 @@ static void kxtj9_report_acceleration_data(struct kxtj9_data *tj9)
if (err < 0)
dev_err(&tj9->client->dev, "accelerometer data read failed\n");
x = le16_to_cpu(acc_data[tj9->pdata.axis_map_x]) >> tj9->shift;
y = le16_to_cpu(acc_data[tj9->pdata.axis_map_y]) >> tj9->shift;
z = le16_to_cpu(acc_data[tj9->pdata.axis_map_z]) >> tj9->shift;
x = le16_to_cpu(acc_data[tj9->pdata.axis_map_x]);
y = le16_to_cpu(acc_data[tj9->pdata.axis_map_y]);
z = le16_to_cpu(acc_data[tj9->pdata.axis_map_z]);
x >>= tj9->shift;
y >>= tj9->shift;
z >>= tj9->shift;
input_report_abs(tj9->input_dev, ABS_X, tj9->pdata.negate_x ? -x : x);
input_report_abs(tj9->input_dev, ABS_Y, tj9->pdata.negate_y ? -y : y);
......@@ -487,7 +499,7 @@ static int __devinit kxtj9_verify(struct kxtj9_data *tj9)
goto out;
}
retval = retval != 0x06 ? -EIO : 0;
retval = (retval != 0x07 && retval != 0x08) ? -EIO : 0;
out:
kxtj9_device_power_off(tj9);
......@@ -537,7 +549,7 @@ static int __devinit kxtj9_probe(struct i2c_client *client,
i2c_set_clientdata(client, tj9);
tj9->ctrl_reg1 = tj9->pdata.res_12bit | tj9->pdata.g_range;
tj9->data_ctrl = tj9->pdata.data_odr_init;
tj9->last_poll_interval = tj9->pdata.init_interval;
if (client->irq) {
/* If in irq mode, populate INT_CTRL_REG1 and enable DRDY. */
......@@ -655,17 +667,7 @@ static struct i2c_driver kxtj9_driver = {
.id_table = kxtj9_id,
};
static int __init kxtj9_init(void)
{
return i2c_add_driver(&kxtj9_driver);
}
module_init(kxtj9_init);
static void __exit kxtj9_exit(void)
{
i2c_del_driver(&kxtj9_driver);
}
module_exit(kxtj9_exit);
module_i2c_driver(kxtj9_driver);
MODULE_DESCRIPTION("KXTJ9 accelerometer driver");
MODULE_AUTHOR("Chris Hudson <chudson@kionix.com>");
......
/**
* max8925_onkey.c - MAX8925 ONKEY driver
* MAX8925 ONKEY driver
*
* Copyright (C) 2009 Marvell International Ltd.
* Haojian Zhuang <haojian.zhuang@marvell.com>
......@@ -35,7 +35,7 @@ struct max8925_onkey_info {
struct input_dev *idev;
struct i2c_client *i2c;
struct device *dev;
int irq[2];
unsigned int irq[2];
};
/*
......@@ -46,17 +46,14 @@ struct max8925_onkey_info {
static irqreturn_t max8925_onkey_handler(int irq, void *data)
{
struct max8925_onkey_info *info = data;
int ret, event;
ret = max8925_reg_read(info->i2c, MAX8925_ON_OFF_STATUS);
if (ret & SW_INPUT)
event = 1;
else
event = 0;
input_report_key(info->idev, KEY_POWER, event);
int state;
state = max8925_reg_read(info->i2c, MAX8925_ON_OFF_STATUS);
input_report_key(info->idev, KEY_POWER, state & SW_INPUT);
input_sync(info->idev);
dev_dbg(info->dev, "onkey event:%d\n", event);
dev_dbg(info->dev, "onkey state:%d\n", state);
/* Enable hardreset to halt if system isn't shutdown on time */
max8925_set_bits(info->i2c, MAX8925_SYSENSEL,
......@@ -69,6 +66,7 @@ static int __devinit max8925_onkey_probe(struct platform_device *pdev)
{
struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct max8925_onkey_info *info;
struct input_dev *input;
int irq[2], error;
irq[0] = platform_get_irq(pdev, 0);
......@@ -76,6 +74,7 @@ static int __devinit max8925_onkey_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "No IRQ resource!\n");
return -EINVAL;
}
irq[1] = platform_get_irq(pdev, 1);
if (irq[1] < 0) {
dev_err(&pdev->dev, "No IRQ resource!\n");
......@@ -83,11 +82,24 @@ static int __devinit max8925_onkey_probe(struct platform_device *pdev)
}
info = kzalloc(sizeof(struct max8925_onkey_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
input = input_allocate_device();
if (!info || !input) {
error = -ENOMEM;
goto err_free_mem;
}
info->idev = input;
info->i2c = chip->i2c;
info->dev = &pdev->dev;
info->irq[0] = irq[0];
info->irq[1] = irq[1];
input->name = "max8925_on";
input->phys = "max8925_on/input0";
input->id.bustype = BUS_I2C;
input->dev.parent = &pdev->dev;
input_set_capability(input, EV_KEY, KEY_POWER);
irq[0] += chip->irq_base;
irq[1] += chip->irq_base;
......@@ -96,60 +108,46 @@ static int __devinit max8925_onkey_probe(struct platform_device *pdev)
if (error < 0) {
dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
irq[0], error);
goto out;
goto err_free_mem;
}
error = request_threaded_irq(irq[1], NULL, max8925_onkey_handler,
IRQF_ONESHOT, "onkey-up", info);
if (error < 0) {
dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
irq[1], error);
goto out_irq;
goto err_free_irq0;
}
info->idev = input_allocate_device();
if (!info->idev) {
dev_err(chip->dev, "Failed to allocate input dev\n");
error = -ENOMEM;
goto out_input;
}
info->idev->name = "max8925_on";
info->idev->phys = "max8925_on/input0";
info->idev->id.bustype = BUS_I2C;
info->idev->dev.parent = &pdev->dev;
info->irq[0] = irq[0];
info->irq[1] = irq[1];
info->idev->evbit[0] = BIT_MASK(EV_KEY);
info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
error = input_register_device(info->idev);
if (error) {
dev_err(chip->dev, "Can't register input device: %d\n", error);
goto out_reg;
goto err_free_irq1;
}
platform_set_drvdata(pdev, info);
device_init_wakeup(&pdev->dev, 1);
return 0;
out_reg:
input_free_device(info->idev);
out_input:
free_irq(info->irq[1], info);
out_irq:
free_irq(info->irq[0], info);
out:
err_free_irq1:
free_irq(irq[1], info);
err_free_irq0:
free_irq(irq[0], info);
err_free_mem:
input_free_device(input);
kfree(info);
return error;
}
static int __devexit max8925_onkey_remove(struct platform_device *pdev)
{
struct max8925_onkey_info *info = platform_get_drvdata(pdev);
struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
free_irq(info->irq[0], info);
free_irq(info->irq[1], info);
free_irq(info->irq[0] + chip->irq_base, info);
free_irq(info->irq[1] + chip->irq_base, info);
input_unregister_device(info->idev);
kfree(info);
......@@ -158,10 +156,43 @@ static int __devexit max8925_onkey_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int max8925_onkey_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct max8925_onkey_info *info = platform_get_drvdata(pdev);
struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
if (device_may_wakeup(dev)) {
chip->wakeup_flag |= 1 << info->irq[0];
chip->wakeup_flag |= 1 << info->irq[1];
}
return 0;
}
static int max8925_onkey_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct max8925_onkey_info *info = platform_get_drvdata(pdev);
struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
if (device_may_wakeup(dev)) {
chip->wakeup_flag &= ~(1 << info->irq[0]);
chip->wakeup_flag &= ~(1 << info->irq[1]);
}
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(max8925_onkey_pm_ops, max8925_onkey_suspend, max8925_onkey_resume);
static struct platform_driver max8925_onkey_driver = {
.driver = {
.name = "max8925-onkey",
.owner = THIS_MODULE,
.pm = &max8925_onkey_pm_ops,
},
.probe = max8925_onkey_probe,
.remove = __devexit_p(max8925_onkey_remove),
......
This diff is collapsed.
......@@ -247,17 +247,7 @@ static struct i2c_driver mma8450_driver = {
.id_table = mma8450_id,
};
static int __init mma8450_init(void)
{
return i2c_add_driver(&mma8450_driver);
}
module_init(mma8450_init);
static void __exit mma8450_exit(void)
{
i2c_del_driver(&mma8450_driver);
}
module_exit(mma8450_exit);
module_i2c_driver(mma8450_driver);
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_DESCRIPTION("MMA8450 3-Axis Accelerometer Driver");
......
......@@ -475,17 +475,7 @@ static struct i2c_driver mpu3050_i2c_driver = {
.id_table = mpu3050_ids,
};
static int __init mpu3050_init(void)
{
return i2c_add_driver(&mpu3050_i2c_driver);
}
module_init(mpu3050_init);
static void __exit mpu3050_exit(void)
{
i2c_del_driver(&mpu3050_i2c_driver);
}
module_exit(mpu3050_exit);
module_i2c_driver(mpu3050_i2c_driver);
MODULE_AUTHOR("Wistron Corp.");
MODULE_DESCRIPTION("MPU3050 Tri-axis gyroscope driver");
......
......@@ -216,17 +216,7 @@ static struct i2c_driver pcf8574_kp_driver = {
.id_table = pcf8574_kp_id,
};
static int __init pcf8574_kp_init(void)
{
return i2c_add_driver(&pcf8574_kp_driver);
}
module_init(pcf8574_kp_init);
static void __exit pcf8574_kp_exit(void)
{
i2c_del_driver(&pcf8574_kp_driver);
}
module_exit(pcf8574_kp_exit);
module_i2c_driver(pcf8574_kp_driver);
MODULE_AUTHOR("Michael Hennerich");
MODULE_DESCRIPTION("Keypad input driver for 16 keys connected to PCF8574");
......
......@@ -172,7 +172,7 @@ static void twl4030_vibra_close(struct input_dev *input)
}
/*** Module ***/
#if CONFIG_PM_SLEEP
#ifdef CONFIG_PM_SLEEP
static int twl4030_vibra_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
......
......@@ -322,4 +322,21 @@ config MOUSE_SYNAPTICS_I2C
To compile this driver as a module, choose M here: the
module will be called synaptics_i2c.
config MOUSE_SYNAPTICS_USB
tristate "Synaptics USB device support"
depends on USB_ARCH_HAS_HCD
select USB
help
Say Y here if you want to use a Synaptics USB touchpad or pointing
stick.
While these devices emulate an USB mouse by default and can be used
with standard usbhid driver, this driver, together with its X.Org
counterpart, allows you to fully utilize capabilities of the device.
More information can be found at:
<http://jan-steinhoff.de/linux/synaptics-usb.html>
To compile this driver as a module, choose M here: the
module will be called synaptics_usb.
endif
......@@ -18,6 +18,7 @@ obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o
obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o
obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o
obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o
obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
psmouse-objs := psmouse-base.o synaptics.o
......
......@@ -433,6 +433,7 @@ static void setup_events_to_report(struct input_dev *input_dev,
__set_bit(BTN_TOOL_QUADTAP, input_dev->keybit);
__set_bit(BTN_LEFT, input_dev->keybit);
__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
if (cfg->caps & HAS_INTEGRATED_BUTTON)
__set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
......
......@@ -640,7 +640,6 @@ static int hgpk_reset_device(struct psmouse *psmouse, bool recalibrate)
static int hgpk_force_recalibrate(struct psmouse *psmouse)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
struct hgpk_data *priv = psmouse->private;
int err;
......@@ -669,12 +668,9 @@ static int hgpk_force_recalibrate(struct psmouse *psmouse)
* we don't have a good way to deal with it. The 2s window stuff
* (below) is our best option for now.
*/
if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE))
if (psmouse_activate(psmouse))
return -1;
psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
if (tpdebug)
psmouse_dbg(psmouse, "touchpad reactivated\n");
......@@ -733,8 +729,7 @@ static int hgpk_toggle_powersave(struct psmouse *psmouse, int enable)
}
/* should be all set, enable the touchpad */
ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE);
psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
psmouse_activate(psmouse);
psmouse_dbg(psmouse, "Touchpad powered up.\n");
} else {
psmouse_dbg(psmouse, "Powering off touchpad.\n");
......
......@@ -1092,28 +1092,33 @@ static void psmouse_initialize(struct psmouse *psmouse)
* psmouse_activate() enables the mouse so that we get motion reports from it.
*/
static void psmouse_activate(struct psmouse *psmouse)
int psmouse_activate(struct psmouse *psmouse)
{
if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE))
if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) {
psmouse_warn(psmouse, "Failed to enable mouse on %s\n",
psmouse->ps2dev.serio->phys);
return -1;
}
psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
return 0;
}
/*
* psmouse_deactivate() puts the mouse into poll mode so that we don't get motion
* reports from it unless we explicitly request it.
*/
static void psmouse_deactivate(struct psmouse *psmouse)
int psmouse_deactivate(struct psmouse *psmouse)
{
if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE))
if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) {
psmouse_warn(psmouse, "Failed to deactivate mouse on %s\n",
psmouse->ps2dev.serio->phys);
return -1;
}
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
return 0;
}
......
......@@ -105,6 +105,8 @@ int psmouse_reset(struct psmouse *psmouse);
void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state);
void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse);
int psmouse_activate(struct psmouse *psmouse);
int psmouse_deactivate(struct psmouse *psmouse);
struct psmouse_attribute {
struct device_attribute dattr;
......
......@@ -90,8 +90,7 @@ static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val)
* to do that for writes because sysfs set helper does this for
* us.
*/
ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
psmouse_deactivate(psmouse);
ps2_begin_command(ps2dev);
......@@ -128,8 +127,7 @@ static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val)
out:
ps2_end_command(ps2dev);
ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
psmouse_activate(psmouse);
dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n",
reg_addr, *reg_val, rc);
return rc;
......@@ -213,8 +211,7 @@ static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val)
unsigned char param[3];
int rc = -1;
ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
psmouse_deactivate(psmouse);
ps2_begin_command(ps2dev);
......@@ -239,8 +236,7 @@ static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val)
out:
ps2_end_command(ps2dev);
ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
psmouse_activate(psmouse);
dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n",
*reg_val, rc);
return rc;
......
......@@ -672,18 +672,7 @@ static struct i2c_driver synaptics_i2c_driver = {
.id_table = synaptics_i2c_id_table,
};
static int __init synaptics_i2c_init(void)
{
return i2c_add_driver(&synaptics_i2c_driver);
}
static void __exit synaptics_i2c_exit(void)
{
i2c_del_driver(&synaptics_i2c_driver);
}
module_init(synaptics_i2c_init);
module_exit(synaptics_i2c_exit);
module_i2c_driver(synaptics_i2c_driver);
MODULE_DESCRIPTION("Synaptics I2C touchpad driver");
MODULE_AUTHOR("Mike Rapoport, Igor Grinberg, Compulab");
......
This diff is collapsed.
/*
* 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);
......@@ -180,8 +180,6 @@ static const struct of_device_id altera_ps2_match[] = {
{},
};
MODULE_DEVICE_TABLE(of, altera_ps2_match);
#else /* CONFIG_OF */
#define altera_ps2_match NULL
#endif /* CONFIG_OF */
/*
......@@ -193,7 +191,7 @@ static struct platform_driver altera_ps2_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
.of_match_table = altera_ps2_match,
.of_match_table = of_match_ptr(altera_ps2_match),
},
};
module_platform_driver(altera_ps2_driver);
......
......@@ -98,9 +98,9 @@ struct psif {
struct serio *io;
void __iomem *regs;
unsigned int irq;
unsigned int open;
/* Prevent concurrent writes to PSIF THR. */
spinlock_t lock;
bool open;
};
static irqreturn_t psif_interrupt(int irq, void *_ptr)
......@@ -164,7 +164,7 @@ static int psif_open(struct serio *io)
psif_writel(psif, CR, PSIF_BIT(CR_TXEN) | PSIF_BIT(CR_RXEN));
psif_writel(psif, IER, PSIF_BIT(RXRDY));
psif->open = 1;
psif->open = true;
out:
return retval;
}
......@@ -173,7 +173,7 @@ static void psif_close(struct serio *io)
{
struct psif *psif = io->port_data;
psif->open = 0;
psif->open = false;
psif_writel(psif, IDR, ~0UL);
psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS));
......@@ -319,9 +319,10 @@ static int __exit psif_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM
static int psif_suspend(struct platform_device *pdev, pm_message_t state)
#ifdef CONFIG_PM_SLEEP
static int psif_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct psif *psif = platform_get_drvdata(pdev);
if (psif->open) {
......@@ -332,8 +333,9 @@ static int psif_suspend(struct platform_device *pdev, pm_message_t state)
return 0;
}
static int psif_resume(struct platform_device *pdev)
static int psif_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct psif *psif = platform_get_drvdata(pdev);
if (psif->open) {
......@@ -344,19 +346,17 @@ static int psif_resume(struct platform_device *pdev)
return 0;
}
#else
#define psif_suspend NULL
#define psif_resume NULL
#endif
static SIMPLE_DEV_PM_OPS(psif_pm_ops, psif_suspend, psif_resume);
static struct platform_driver psif_driver = {
.remove = __exit_p(psif_remove),
.driver = {
.name = "atmel_psif",
.owner = THIS_MODULE,
.pm = &psif_pm_ops,
},
.suspend = psif_suspend,
.resume = psif_resume,
};
static int __init psif_init(void)
......
......@@ -44,26 +44,31 @@
#include <asm/irq.h>
#include <asm/q40ints.h>
#define DRV_NAME "q40kbd"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
static DEFINE_SPINLOCK(q40kbd_lock);
static struct serio *q40kbd_port;
static struct platform_device *q40kbd_device;
struct q40kbd {
struct serio *port;
spinlock_t lock;
};
static irqreturn_t q40kbd_interrupt(int irq, void *dev_id)
{
struct q40kbd *q40kbd = dev_id;
unsigned long flags;
spin_lock_irqsave(&q40kbd_lock, flags);
spin_lock_irqsave(&q40kbd->lock, flags);
if (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))
serio_interrupt(q40kbd_port, master_inb(KEYCODE_REG), 0);
serio_interrupt(q40kbd->port, master_inb(KEYCODE_REG), 0);
master_outb(-1, KEYBOARD_UNLOCK_REG);
spin_unlock_irqrestore(&q40kbd_lock, flags);
spin_unlock_irqrestore(&q40kbd->lock, flags);
return IRQ_HANDLED;
}
......@@ -72,17 +77,23 @@ static irqreturn_t q40kbd_interrupt(int irq, void *dev_id)
* q40kbd_flush() flushes all data that may be in the keyboard buffers
*/
static void q40kbd_flush(void)
static void q40kbd_flush(struct q40kbd *q40kbd)
{
int maxread = 100;
unsigned long flags;
spin_lock_irqsave(&q40kbd_lock, flags);
spin_lock_irqsave(&q40kbd->lock, flags);
while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
master_inb(KEYCODE_REG);
spin_unlock_irqrestore(&q40kbd_lock, flags);
spin_unlock_irqrestore(&q40kbd->lock, flags);
}
static void q40kbd_stop(void)
{
master_outb(0, KEY_IRQ_ENABLE_REG);
master_outb(-1, KEYBOARD_UNLOCK_REG);
}
/*
......@@ -92,12 +103,9 @@ static void q40kbd_flush(void)
static int q40kbd_open(struct serio *port)
{
q40kbd_flush();
struct q40kbd *q40kbd = port->port_data;
if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) {
printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD);
return -EBUSY;
}
q40kbd_flush(q40kbd);
/* off we go */
master_outb(-1, KEYBOARD_UNLOCK_REG);
......@@ -108,36 +116,72 @@ static int q40kbd_open(struct serio *port)
static void q40kbd_close(struct serio *port)
{
master_outb(0, KEY_IRQ_ENABLE_REG);
master_outb(-1, KEYBOARD_UNLOCK_REG);
free_irq(Q40_IRQ_KEYBOARD, NULL);
struct q40kbd *q40kbd = port->port_data;
q40kbd_flush();
q40kbd_stop();
q40kbd_flush(q40kbd);
}
static int __devinit q40kbd_probe(struct platform_device *dev)
static int __devinit q40kbd_probe(struct platform_device *pdev)
{
q40kbd_port = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!q40kbd_port)
return -ENOMEM;
q40kbd_port->id.type = SERIO_8042;
q40kbd_port->open = q40kbd_open;
q40kbd_port->close = q40kbd_close;
q40kbd_port->dev.parent = &dev->dev;
strlcpy(q40kbd_port->name, "Q40 Kbd Port", sizeof(q40kbd_port->name));
strlcpy(q40kbd_port->phys, "Q40", sizeof(q40kbd_port->phys));
serio_register_port(q40kbd_port);
struct q40kbd *q40kbd;
struct serio *port;
int error;
q40kbd = kzalloc(sizeof(struct q40kbd), GFP_KERNEL);
port = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!q40kbd || !port) {
error = -ENOMEM;
goto err_free_mem;
}
q40kbd->port = port;
spin_lock_init(&q40kbd->lock);
port->id.type = SERIO_8042;
port->open = q40kbd_open;
port->close = q40kbd_close;
port->port_data = q40kbd;
port->dev.parent = &pdev->dev;
strlcpy(port->name, "Q40 Kbd Port", sizeof(port->name));
strlcpy(port->phys, "Q40", sizeof(port->phys));
q40kbd_stop();
error = request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0,
DRV_NAME, q40kbd);
if (error) {
dev_err(&pdev->dev, "Can't get irq %d.\n", Q40_IRQ_KEYBOARD);
goto err_free_mem;
}
serio_register_port(q40kbd->port);
platform_set_drvdata(pdev, q40kbd);
printk(KERN_INFO "serio: Q40 kbd registered\n");
return 0;
err_free_mem:
kfree(port);
kfree(q40kbd);
return error;
}
static int __devexit q40kbd_remove(struct platform_device *dev)
static int __devexit q40kbd_remove(struct platform_device *pdev)
{
serio_unregister_port(q40kbd_port);
struct q40kbd *q40kbd = platform_get_drvdata(pdev);
/*
* q40kbd_close() will be called as part of unregistering
* and will ensure that IRQ is turned off, so it is safe
* to unregister port first and free IRQ later.
*/
serio_unregister_port(q40kbd->port);
free_irq(Q40_IRQ_KEYBOARD, q40kbd);
kfree(q40kbd);
platform_set_drvdata(pdev, NULL);
return 0;
}
......@@ -146,41 +190,16 @@ static struct platform_driver q40kbd_driver = {
.name = "q40kbd",
.owner = THIS_MODULE,
},
.probe = q40kbd_probe,
.remove = __devexit_p(q40kbd_remove),
};
static int __init q40kbd_init(void)
{
int error;
if (!MACH_IS_Q40)
return -ENODEV;
error = platform_driver_register(&q40kbd_driver);
if (error)
return error;
q40kbd_device = platform_device_alloc("q40kbd", -1);
if (!q40kbd_device)
goto err_unregister_driver;
error = platform_device_add(q40kbd_device);
if (error)
goto err_free_device;
return 0;
err_free_device:
platform_device_put(q40kbd_device);
err_unregister_driver:
platform_driver_unregister(&q40kbd_driver);
return error;
return platform_driver_probe(&q40kbd_driver, q40kbd_probe);
}
static void __exit q40kbd_exit(void)
{
platform_device_unregister(q40kbd_device);
platform_driver_unregister(&q40kbd_driver);
}
......
......@@ -176,7 +176,7 @@ static int wacom_parse_logical_collection(unsigned char *report,
/* Logical collection is only used by 3rd gen Bamboo Touch */
features->pktlen = WACOM_PKGLEN_BBTOUCH3;
features->device_type = BTN_TOOL_DOUBLETAP;
features->device_type = BTN_TOOL_FINGER;
/*
* Stylus and Touch have same active area
......@@ -184,9 +184,9 @@ static int wacom_parse_logical_collection(unsigned char *report,
* data before its overwritten.
*/
features->x_phy =
(features->x_max * features->x_resolution) / 100;
(features->x_max * 100) / features->x_resolution;
features->y_phy =
(features->y_max * features->y_resolution) / 100;
(features->y_max * 100) / features->y_resolution;
features->x_max = features->y_max =
get_unaligned_le16(&report[10]);
......@@ -286,12 +286,10 @@ static int wacom_parse_hid(struct usb_interface *intf,
if (features->type == TABLETPC2FG) {
/* need to reset back */
features->pktlen = WACOM_PKGLEN_TPC2FG;
features->device_type = BTN_TOOL_DOUBLETAP;
}
if (features->type == BAMBOO_PT) {
/* need to reset back */
features->pktlen = WACOM_PKGLEN_BBTOUCH;
features->device_type = BTN_TOOL_DOUBLETAP;
features->x_phy =
get_unaligned_le16(&report[i + 5]);
features->x_max =
......@@ -325,7 +323,6 @@ static int wacom_parse_hid(struct usb_interface *intf,
if (features->type == TABLETPC2FG) {
/* need to reset back */
features->pktlen = WACOM_PKGLEN_TPC2FG;
features->device_type = BTN_TOOL_DOUBLETAP;
features->y_max =
get_unaligned_le16(&report[i + 3]);
features->y_phy =
......@@ -334,7 +331,6 @@ static int wacom_parse_hid(struct usb_interface *intf,
} else if (features->type == BAMBOO_PT) {
/* need to reset back */
features->pktlen = WACOM_PKGLEN_BBTOUCH;
features->device_type = BTN_TOOL_DOUBLETAP;
features->y_phy =
get_unaligned_le16(&report[i + 3]);
features->y_max =
......
......@@ -832,12 +832,24 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
dbg("wacom_tpc_irq: received report #%d", data[0]);
if (len == WACOM_PKGLEN_TPC1FG || data[0] == WACOM_REPORT_TPC1FG)
switch (len) {
case WACOM_PKGLEN_TPC1FG:
return wacom_tpc_single_touch(wacom, len);
else if (data[0] == WACOM_REPORT_TPC2FG)
case WACOM_PKGLEN_TPC2FG:
return wacom_tpc_mt_touch(wacom);
else if (data[0] == WACOM_REPORT_PENABLED)
default:
switch (data[0]) {
case WACOM_REPORT_TPC1FG:
case WACOM_REPORT_TPCHID:
case WACOM_REPORT_TPCST:
return wacom_tpc_single_touch(wacom, len);
case WACOM_REPORT_PENABLED:
return wacom_tpc_pen(wacom);
}
}
return 0;
}
......@@ -1317,7 +1329,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
break;
case TABLETPC2FG:
if (features->device_type == BTN_TOOL_DOUBLETAP) {
if (features->device_type == BTN_TOOL_FINGER) {
input_mt_init_slots(input_dev, 2);
input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
......@@ -1366,7 +1378,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
if (features->device_type == BTN_TOOL_DOUBLETAP) {
if (features->device_type == BTN_TOOL_FINGER) {
__set_bit(BTN_LEFT, input_dev->keybit);
__set_bit(BTN_FORWARD, input_dev->keybit);
__set_bit(BTN_BACK, input_dev->keybit);
......
......@@ -39,6 +39,8 @@
#define WACOM_REPORT_INTUOSPAD 12
#define WACOM_REPORT_TPC1FG 6
#define WACOM_REPORT_TPC2FG 13
#define WACOM_REPORT_TPCHID 15
#define WACOM_REPORT_TPCST 16
/* device quirks */
#define WACOM_QUIRK_MULTI_INPUT 0x0001
......
......@@ -139,7 +139,6 @@ config TOUCHSCREEN_CY8CTMG110
tristate "cy8ctmg110 touchscreen"
depends on I2C
depends on GPIOLIB
help
Say Y here if you have a cy8ctmg110 capacitive touchscreen on
an AAVA device.
......@@ -149,6 +148,37 @@ config TOUCHSCREEN_CY8CTMG110
To compile this driver as a module, choose M here: the
module will be called cy8ctmg110_ts.
config TOUCHSCREEN_CYTTSP_CORE
tristate "Cypress TTSP touchscreen"
help
Say Y here if you have a touchscreen using controller from
the Cypress TrueTouch(tm) Standard Product family connected
to your system. You will also need to select appropriate
bus connection below.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called cyttsp_core.
config TOUCHSCREEN_CYTTSP_I2C
tristate "support I2C bus connection"
depends on TOUCHSCREEN_CYTTSP_CORE && I2C
help
Say Y here if the touchscreen is connected via I2C bus.
To compile this driver as a module, choose M here: the
module will be called cyttsp_i2c.
config TOUCHSCREEN_CYTTSP_SPI
tristate "support SPI bus connection"
depends on TOUCHSCREEN_CYTTSP_CORE && SPI_MASTER
help
Say Y here if the touchscreen is connected via SPI bus.
To compile this driver as a module, choose M here: the
module will be called cyttsp_spi.
config TOUCHSCREEN_DA9034
tristate "Touchscreen support for Dialog Semiconductor DA9034"
depends on PMIC_DA903X
......@@ -213,6 +243,21 @@ config TOUCHSCREEN_FUJITSU
To compile this driver as a module, choose M here: the
module will be called fujitsu-ts.
config TOUCHSCREEN_ILI210X
tristate "Ilitek ILI210X based touchscreen"
depends on I2C
help
Say Y here if you have a ILI210X based touchscreen
controller. This driver supports models ILI2102,
ILI2102s, ILI2103, ILI2103s and ILI2105.
Such kind of chipsets can be found in Amazon Kindle Fire
touchscreens.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called ili210x.
config TOUCHSCREEN_S3C2410
tristate "Samsung S3C2410/generic touchscreen input driver"
depends on ARCH_S3C2410 || SAMSUNG_DEV_TS
......@@ -430,6 +475,18 @@ config TOUCHSCREEN_TOUCHWIN
To compile this driver as a module, choose M here: the
module will be called touchwin.
config TOUCHSCREEN_TI_TSCADC
tristate "TI Touchscreen Interface"
depends on ARCH_OMAP2PLUS
help
Say Y here if you have 4/5/8 wire touchscreen controller
to be connected to the ADC controller on your TI AM335x SoC.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called ti_tscadc.
config TOUCHSCREEN_ATMEL_TSADCC
tristate "Atmel Touchscreen Interface"
depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
......@@ -577,6 +634,7 @@ config TOUCHSCREEN_USB_COMPOSITE
- JASTEC USB Touch Controller/DigiTech DTR-02U
- Zytronic controllers
- Elo TouchSystems 2700 IntelliTouch
- EasyTouch USB Touch Controller from Data Modul
Have a look at <http://linux.chapter7.ch/touchkit/> for
a usage description and the required user-space stuff.
......@@ -681,6 +739,14 @@ config TOUCHSCREEN_USB_NEXIO
bool "NEXIO/iNexio device support" if EXPERT
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_EASYTOUCH
default y
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.
If unsure, say N.
config TOUCHSCREEN_TOUCHIT213
tristate "Sahara TouchIT-213 touchscreen"
select SERIO
......
......@@ -18,6 +18,9 @@ obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o
obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o
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_DYNAPRO) += dynapro.o
obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o
......@@ -26,6 +29,7 @@ obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o
......@@ -45,6 +49,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o
obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o
obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
obj-$(CONFIG_TOUCHSCREEN_TI_TSCADC) += ti_tscadc.o
obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
......
......@@ -860,17 +860,7 @@ static struct spi_driver ad7877_driver = {
.remove = __devexit_p(ad7877_remove),
};
static int __init ad7877_init(void)
{
return spi_register_driver(&ad7877_driver);
}
module_init(ad7877_init);
static void __exit ad7877_exit(void)
{
spi_unregister_driver(&ad7877_driver);
}
module_exit(ad7877_exit);
module_spi_driver(ad7877_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("AD7877 touchscreen Driver");
......
......@@ -102,17 +102,7 @@ static struct i2c_driver ad7879_i2c_driver = {
.id_table = ad7879_id,
};
static int __init ad7879_i2c_init(void)
{
return i2c_add_driver(&ad7879_i2c_driver);
}
module_init(ad7879_i2c_init);
static void __exit ad7879_i2c_exit(void)
{
i2c_del_driver(&ad7879_i2c_driver);
}
module_exit(ad7879_i2c_exit);
module_i2c_driver(ad7879_i2c_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("AD7879(-1) touchscreen I2C bus driver");
......
......@@ -157,17 +157,7 @@ static struct spi_driver ad7879_spi_driver = {
.remove = __devexit_p(ad7879_spi_remove),
};
static int __init ad7879_spi_init(void)
{
return spi_register_driver(&ad7879_spi_driver);
}
module_init(ad7879_spi_init);
static void __exit ad7879_spi_exit(void)
{
spi_unregister_driver(&ad7879_spi_driver);
}
module_exit(ad7879_spi_exit);
module_spi_driver(ad7879_spi_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("AD7879(-1) touchscreen SPI bus driver");
......
......@@ -1433,17 +1433,7 @@ static struct spi_driver ads7846_driver = {
.remove = __devexit_p(ads7846_remove),
};
static int __init ads7846_init(void)
{
return spi_register_driver(&ads7846_driver);
}
module_init(ads7846_init);
static void __exit ads7846_exit(void)
{
spi_unregister_driver(&ads7846_driver);
}
module_exit(ads7846_exit);
module_spi_driver(ads7846_driver);
MODULE_DESCRIPTION("ADS7846 TouchScreen Driver");
MODULE_LICENSE("GPL");
......
......@@ -392,9 +392,10 @@ static int __exit atmel_wm97xx_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM
static int atmel_wm97xx_suspend(struct platform_device *pdev, pm_message_t msg)
#ifdef CONFIG_PM_SLEEP
static int atmel_wm97xx_suspend(struct *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT);
......@@ -404,8 +405,9 @@ static int atmel_wm97xx_suspend(struct platform_device *pdev, pm_message_t msg)
return 0;
}
static int atmel_wm97xx_resume(struct platform_device *pdev)
static int atmel_wm97xx_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
struct wm97xx *wm = atmel_wm97xx->wm;
......@@ -416,18 +418,18 @@ static int atmel_wm97xx_resume(struct platform_device *pdev)
return 0;
}
#else
#define atmel_wm97xx_suspend NULL
#define atmel_wm97xx_resume NULL
#endif
static SIMPLE_DEV_PM_OPS(atmel_wm97xx_pm_ops,
atmel_wm97xx_suspend, atmel_wm97xx_resume);
static struct platform_driver atmel_wm97xx_driver = {
.remove = __exit_p(atmel_wm97xx_remove),
.driver = {
.name = "wm97xx-touch",
.owner = THIS_MODULE,
.pm = &atmel_wm97xx_pm_ops,
},
.suspend = atmel_wm97xx_suspend,
.resume = atmel_wm97xx_resume,
};
static int __init atmel_wm97xx_init(void)
......
......@@ -1267,18 +1267,7 @@ static struct i2c_driver mxt_driver = {
.id_table = mxt_id,
};
static int __init mxt_init(void)
{
return i2c_add_driver(&mxt_driver);
}
static void __exit mxt_exit(void)
{
i2c_del_driver(&mxt_driver);
}
module_init(mxt_init);
module_exit(mxt_exit);
module_i2c_driver(mxt_driver);
/* Module information */
MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
......
......@@ -635,17 +635,7 @@ static struct i2c_driver auo_pixcir_driver = {
.id_table = auo_pixcir_idtable,
};
static int __init auo_pixcir_init(void)
{
return i2c_add_driver(&auo_pixcir_driver);
}
module_init(auo_pixcir_init);
static void __exit auo_pixcir_exit(void)
{
i2c_del_driver(&auo_pixcir_driver);
}
module_exit(auo_pixcir_exit);
module_i2c_driver(auo_pixcir_driver);
MODULE_DESCRIPTION("AUO-PIXCIR touchscreen driver");
MODULE_LICENSE("GPL v2");
......
......@@ -652,30 +652,7 @@ static struct i2c_driver bu21013_driver = {
.id_table = bu21013_id,
};
/**
* bu21013_init() - initializes the bu21013 touchscreen driver
*
* This function used to initializes the bu21013
* touchscreen driver and returns integer.
*/
static int __init bu21013_init(void)
{
return i2c_add_driver(&bu21013_driver);
}
/**
* bu21013_exit() - de-initializes the bu21013 touchscreen driver
*
* This function uses to de-initializes the bu21013
* touchscreen driver and returns none.
*/
static void __exit bu21013_exit(void)
{
i2c_del_driver(&bu21013_driver);
}
module_init(bu21013_init);
module_exit(bu21013_exit);
module_i2c_driver(bu21013_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Naveen Kumar G <naveen.gaddipati@stericsson.com>");
......
......@@ -350,18 +350,7 @@ static struct i2c_driver cy8ctmg110_driver = {
.remove = __devexit_p(cy8ctmg110_remove),
};
static int __init cy8ctmg110_init(void)
{
return i2c_add_driver(&cy8ctmg110_driver);
}
static void __exit cy8ctmg110_exit(void)
{
i2c_del_driver(&cy8ctmg110_driver);
}
module_init(cy8ctmg110_init);
module_exit(cy8ctmg110_exit);
module_i2c_driver(cy8ctmg110_driver);
MODULE_AUTHOR("Samuli Konttila <samuli.konttila@aavamobile.com>");
MODULE_DESCRIPTION("cy8ctmg110 TouchScreen Driver");
......
This diff is collapsed.
/*
* Header file for:
* Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
* For use with Cypress Txx3xx parts.
* Supported parts include:
* CY8CTST341
* CY8CTMA340
*
* Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
* Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com>
*
*/
#ifndef __CYTTSP_CORE_H__
#define __CYTTSP_CORE_H__
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/device.h>
#include <linux/input/cyttsp.h>
#define CY_NUM_RETRY 16 /* max number of retries for read ops */
struct cyttsp_tch {
__be16 x, y;
u8 z;
} __packed;
/* TrueTouch Standard Product Gen3 interface definition */
struct cyttsp_xydata {
u8 hst_mode;
u8 tt_mode;
u8 tt_stat;
struct cyttsp_tch tch1;
u8 touch12_id;
struct cyttsp_tch tch2;
u8 gest_cnt;
u8 gest_id;
struct cyttsp_tch tch3;
u8 touch34_id;
struct cyttsp_tch tch4;
u8 tt_undef[3];
u8 act_dist;
u8 tt_reserved;
} __packed;
/* TTSP System Information interface definition */
struct cyttsp_sysinfo_data {
u8 hst_mode;
u8 mfg_cmd;
u8 mfg_stat;
u8 cid[3];
u8 tt_undef1;
u8 uid[8];
u8 bl_verh;
u8 bl_verl;
u8 tts_verh;
u8 tts_verl;
u8 app_idh;
u8 app_idl;
u8 app_verh;
u8 app_verl;
u8 tt_undef[5];
u8 scn_typ;
u8 act_intrvl;
u8 tch_tmout;
u8 lp_intrvl;
};
/* TTSP Bootloader Register Map interface definition */
#define CY_BL_CHKSUM_OK 0x01
struct cyttsp_bootloader_data {
u8 bl_file;
u8 bl_status;
u8 bl_error;
u8 blver_hi;
u8 blver_lo;
u8 bld_blver_hi;
u8 bld_blver_lo;
u8 ttspver_hi;
u8 ttspver_lo;
u8 appid_hi;
u8 appid_lo;
u8 appver_hi;
u8 appver_lo;
u8 cid_0;
u8 cid_1;
u8 cid_2;
};
struct cyttsp;
struct cyttsp_bus_ops {
u16 bustype;
int (*write)(struct cyttsp *ts,
u8 addr, u8 length, const void *values);
int (*read)(struct cyttsp *ts, u8 addr, u8 length, void *values);
};
enum cyttsp_state {
CY_IDLE_STATE,
CY_ACTIVE_STATE,
CY_BL_STATE,
};
struct cyttsp {
struct device *dev;
int irq;
struct input_dev *input;
char phys[32];
const struct cyttsp_platform_data *pdata;
const struct cyttsp_bus_ops *bus_ops;
struct cyttsp_bootloader_data bl_data;
struct cyttsp_sysinfo_data sysinfo_data;
struct cyttsp_xydata xy_data;
struct completion bl_ready;
enum cyttsp_state state;
bool suspended;
u8 xfer_buf[] ____cacheline_aligned;
};
struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
struct device *dev, int irq, size_t xfer_buf_size);
void cyttsp_remove(struct cyttsp *ts);
extern const struct dev_pm_ops cyttsp_pm_ops;
#endif /* __CYTTSP_CORE_H__ */
/*
* Source for:
* Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver.
* For use with Cypress Txx3xx parts.
* Supported parts include:
* CY8CTST341
* CY8CTMA340
*
* Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
* Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com>
*
*/
#include "cyttsp_core.h"
#include <linux/i2c.h>
#include <linux/input.h>
#define CY_I2C_DATA_SIZE 128
static int cyttsp_i2c_read_block_data(struct cyttsp *ts,
u8 addr, u8 length, void *values)
{
struct i2c_client *client = to_i2c_client(ts->dev);
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = 0,
.len = 1,
.buf = &addr,
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = length,
.buf = values,
},
};
int retval;
retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (retval < 0)
return retval;
return retval != ARRAY_SIZE(msgs) ? -EIO : 0;
}
static int cyttsp_i2c_write_block_data(struct cyttsp *ts,
u8 addr, u8 length, const void *values)
{
struct i2c_client *client = to_i2c_client(ts->dev);
int retval;
ts->xfer_buf[0] = addr;
memcpy(&ts->xfer_buf[1], values, length);
retval = i2c_master_send(client, ts->xfer_buf, length + 1);
return retval < 0 ? retval : 0;
}
static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = {
.bustype = BUS_I2C,
.write = cyttsp_i2c_write_block_data,
.read = cyttsp_i2c_read_block_data,
};
static int __devinit cyttsp_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct cyttsp *ts;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
dev_err(&client->dev, "I2C functionality not Supported\n");
return -EIO;
}
ts = cyttsp_probe(&cyttsp_i2c_bus_ops, &client->dev, client->irq,
CY_I2C_DATA_SIZE);
if (IS_ERR(ts))
return PTR_ERR(ts);
i2c_set_clientdata(client, ts);
return 0;
}
static int __devexit cyttsp_i2c_remove(struct i2c_client *client)
{
struct cyttsp *ts = i2c_get_clientdata(client);
cyttsp_remove(ts);
return 0;
}
static const struct i2c_device_id cyttsp_i2c_id[] = {
{ CY_I2C_NAME, 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id);
static struct i2c_driver cyttsp_i2c_driver = {
.driver = {
.name = CY_I2C_NAME,
.owner = THIS_MODULE,
.pm = &cyttsp_pm_ops,
},
.probe = cyttsp_i2c_probe,
.remove = __devexit_p(cyttsp_i2c_remove),
.id_table = cyttsp_i2c_id,
};
module_i2c_driver(cyttsp_i2c_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver");
MODULE_AUTHOR("Cypress");
MODULE_ALIAS("i2c:cyttsp");
/*
* Source for:
* Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver.
* For use with Cypress Txx3xx parts.
* Supported parts include:
* CY8CTST341
* CY8CTMA340
*
* Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
* Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com>
*
*/
#include "cyttsp_core.h"
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/spi/spi.h>
#define CY_SPI_WR_OP 0x00 /* r/~w */
#define CY_SPI_RD_OP 0x01
#define CY_SPI_CMD_BYTES 4
#define CY_SPI_SYNC_BYTE 2
#define CY_SPI_SYNC_ACK1 0x62 /* from protocol v.2 */
#define CY_SPI_SYNC_ACK2 0x9D /* from protocol v.2 */
#define CY_SPI_DATA_SIZE 128
#define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE)
#define CY_SPI_BITS_PER_WORD 8
static int cyttsp_spi_xfer(struct cyttsp *ts,
u8 op, u8 reg, u8 *buf, int length)
{
struct spi_device *spi = to_spi_device(ts->dev);
struct spi_message msg;
struct spi_transfer xfer[2];
u8 *wr_buf = &ts->xfer_buf[0];
u8 *rd_buf = &ts->xfer_buf[CY_SPI_DATA_BUF_SIZE];
int retval;
int i;
if (length > CY_SPI_DATA_SIZE) {
dev_err(ts->dev, "%s: length %d is too big.\n",
__func__, length);
return -EINVAL;
}
memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE);
memset(rd_buf, 0, CY_SPI_DATA_BUF_SIZE);
wr_buf[0] = 0x00; /* header byte 0 */
wr_buf[1] = 0xFF; /* header byte 1 */
wr_buf[2] = reg; /* reg index */
wr_buf[3] = op; /* r/~w */
if (op == CY_SPI_WR_OP)
memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length);
memset(xfer, 0, sizeof(xfer));
spi_message_init(&msg);
/*
We set both TX and RX buffers because Cypress TTSP
requires full duplex operation.
*/
xfer[0].tx_buf = wr_buf;
xfer[0].rx_buf = rd_buf;
switch (op) {
case CY_SPI_WR_OP:
xfer[0].len = length + CY_SPI_CMD_BYTES;
spi_message_add_tail(&xfer[0], &msg);
break;
case CY_SPI_RD_OP:
xfer[0].len = CY_SPI_CMD_BYTES;
spi_message_add_tail(&xfer[0], &msg);
xfer[1].rx_buf = buf;
xfer[1].len = length;
spi_message_add_tail(&xfer[1], &msg);
break;
default:
dev_err(ts->dev, "%s: bad operation code=%d\n", __func__, op);
return -EINVAL;
}
retval = spi_sync(spi, &msg);
if (retval < 0) {
dev_dbg(ts->dev, "%s: spi_sync() error %d, len=%d, op=%d\n",
__func__, retval, xfer[1].len, op);
/*
* do not return here since was a bad ACK sequence
* let the following ACK check handle any errors and
* allow silent retries
*/
}
if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK1 ||
rd_buf[CY_SPI_SYNC_BYTE + 1] != CY_SPI_SYNC_ACK2) {
dev_dbg(ts->dev, "%s: operation %d failed\n", __func__, op);
for (i = 0; i < CY_SPI_CMD_BYTES; i++)
dev_dbg(ts->dev, "%s: test rd_buf[%d]:0x%02x\n",
__func__, i, rd_buf[i]);
for (i = 0; i < length; i++)
dev_dbg(ts->dev, "%s: test buf[%d]:0x%02x\n",
__func__, i, buf[i]);
return -EIO;
}
return 0;
}
static int cyttsp_spi_read_block_data(struct cyttsp *ts,
u8 addr, u8 length, void *data)
{
return cyttsp_spi_xfer(ts, CY_SPI_RD_OP, addr, data, length);
}
static int cyttsp_spi_write_block_data(struct cyttsp *ts,
u8 addr, u8 length, const void *data)
{
return cyttsp_spi_xfer(ts, CY_SPI_WR_OP, addr, (void *)data, length);
}
static const struct cyttsp_bus_ops cyttsp_spi_bus_ops = {
.bustype = BUS_SPI,
.write = cyttsp_spi_write_block_data,
.read = cyttsp_spi_read_block_data,
};
static int __devinit cyttsp_spi_probe(struct spi_device *spi)
{
struct cyttsp *ts;
int error;
/* Set up SPI*/
spi->bits_per_word = CY_SPI_BITS_PER_WORD;
spi->mode = SPI_MODE_0;
error = spi_setup(spi);
if (error < 0) {
dev_err(&spi->dev, "%s: SPI setup error %d\n",
__func__, error);
return error;
}
ts = cyttsp_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq,
CY_SPI_DATA_BUF_SIZE * 2);
if (IS_ERR(ts))
return PTR_ERR(ts);
spi_set_drvdata(spi, ts);
return 0;
}
static int __devexit cyttsp_spi_remove(struct spi_device *spi)
{
struct cyttsp *ts = spi_get_drvdata(spi);
cyttsp_remove(ts);
return 0;
}
static struct spi_driver cyttsp_spi_driver = {
.driver = {
.name = CY_SPI_NAME,
.owner = THIS_MODULE,
.pm = &cyttsp_pm_ops,
},
.probe = cyttsp_spi_probe,
.remove = __devexit_p(cyttsp_spi_remove),
};
module_spi_driver(cyttsp_spi_driver);
MODULE_ALIAS("spi:cyttsp");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver");
MODULE_AUTHOR("Cypress");
MODULE_ALIAS("spi:cyttsp");
......@@ -320,20 +320,8 @@ static struct i2c_driver eeti_ts_driver = {
.id_table = eeti_ts_id,
};
static int __init eeti_ts_init(void)
{
return i2c_add_driver(&eeti_ts_driver);
}
static void __exit eeti_ts_exit(void)
{
i2c_del_driver(&eeti_ts_driver);
}
module_i2c_driver(eeti_ts_driver);
MODULE_DESCRIPTION("EETI Touchscreen driver");
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
MODULE_LICENSE("GPL");
module_init(eeti_ts_init);
module_exit(eeti_ts_exit);
......@@ -285,18 +285,7 @@ static struct i2c_driver egalax_ts_driver = {
.remove = __devexit_p(egalax_ts_remove),
};
static int __init egalax_ts_init(void)
{
return i2c_add_driver(&egalax_ts_driver);
}
static void __exit egalax_ts_exit(void)
{
i2c_del_driver(&egalax_ts_driver);
}
module_init(egalax_ts_init);
module_exit(egalax_ts_exit);
module_i2c_driver(egalax_ts_driver);
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_DESCRIPTION("Touchscreen driver for EETI eGalax touch controller");
......
......@@ -93,7 +93,7 @@ static int __init hp680_ts_init(void)
hp680_ts_dev->phys = "hp680_ts/input0";
if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt,
0, MODNAME, 0) < 0) {
0, MODNAME, NULL) < 0) {
printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n",
HP680_TS_IRQ);
err = -EBUSY;
......
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/input/ili210x.h>
#define MAX_TOUCHES 2
#define DEFAULT_POLL_PERIOD 20
/* Touchscreen commands */
#define REG_TOUCHDATA 0x10
#define REG_PANEL_INFO 0x20
#define REG_FIRMWARE_VERSION 0x40
#define REG_CALIBRATE 0xcc
struct finger {
u8 x_low;
u8 x_high;
u8 y_low;
u8 y_high;
} __packed;
struct touchdata {
u8 status;
struct finger finger[MAX_TOUCHES];
} __packed;
struct panel_info {
struct finger finger_max;
u8 xchannel_num;
u8 ychannel_num;
} __packed;
struct firmware_version {
u8 id;
u8 major;
u8 minor;
} __packed;
struct ili210x {
struct i2c_client *client;
struct input_dev *input;
bool (*get_pendown_state)(void);
unsigned int poll_period;
struct delayed_work dwork;
};
static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf,
size_t len)
{
struct i2c_msg msg[2] = {
{
.addr = client->addr,
.flags = 0,
.len = 1,
.buf = &reg,
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = buf,
}
};
if (i2c_transfer(client->adapter, msg, 2) != 2) {
dev_err(&client->dev, "i2c transfer failed\n");
return -EIO;
}
return 0;
}
static void ili210x_report_events(struct input_dev *input,
const struct touchdata *touchdata)
{
int i;
bool touch;
unsigned int x, y;
const struct finger *finger;
for (i = 0; i < MAX_TOUCHES; i++) {
input_mt_slot(input, i);
finger = &touchdata->finger[i];
touch = touchdata->status & (1 << i);
input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
if (touch) {
x = finger->x_low | (finger->x_high << 8);
y = finger->y_low | (finger->y_high << 8);
input_report_abs(input, ABS_MT_POSITION_X, x);
input_report_abs(input, ABS_MT_POSITION_Y, y);
}
}
input_mt_report_pointer_emulation(input, false);
input_sync(input);
}
static bool get_pendown_state(const struct ili210x *priv)
{
bool state = false;
if (priv->get_pendown_state)
state = priv->get_pendown_state();
return state;
}
static void ili210x_work(struct work_struct *work)
{
struct ili210x *priv = container_of(work, struct ili210x,
dwork.work);
struct i2c_client *client = priv->client;
struct touchdata touchdata;
int error;
error = ili210x_read_reg(client, REG_TOUCHDATA,
&touchdata, sizeof(touchdata));
if (error) {
dev_err(&client->dev,
"Unable to get touchdata, err = %d\n", error);
return;
}
ili210x_report_events(priv->input, &touchdata);
if ((touchdata.status & 0xf3) || get_pendown_state(priv))
schedule_delayed_work(&priv->dwork,
msecs_to_jiffies(priv->poll_period));
}
static irqreturn_t ili210x_irq(int irq, void *irq_data)
{
struct ili210x *priv = irq_data;
schedule_delayed_work(&priv->dwork, 0);
return IRQ_HANDLED;
}
static ssize_t ili210x_calibrate(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct ili210x *priv = i2c_get_clientdata(client);
unsigned long calibrate;
int rc;
u8 cmd = REG_CALIBRATE;
if (kstrtoul(buf, 10, &calibrate))
return -EINVAL;
if (calibrate > 1)
return -EINVAL;
if (calibrate) {
rc = i2c_master_send(priv->client, &cmd, sizeof(cmd));
if (rc != sizeof(cmd))
return -EIO;
}
return count;
}
static DEVICE_ATTR(calibrate, 0644, NULL, ili210x_calibrate);
static struct attribute *ili210x_attributes[] = {
&dev_attr_calibrate.attr,
NULL,
};
static const struct attribute_group ili210x_attr_group = {
.attrs = ili210x_attributes,
};
static int __devinit ili210x_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
const struct ili210x_platform_data *pdata = dev->platform_data;
struct ili210x *priv;
struct input_dev *input;
struct panel_info panel;
struct firmware_version firmware;
int xmax, ymax;
int error;
dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver");
if (!pdata) {
dev_err(dev, "No platform data!\n");
return -EINVAL;
}
if (client->irq <= 0) {
dev_err(dev, "No IRQ!\n");
return -EINVAL;
}
/* Get firmware version */
error = ili210x_read_reg(client, REG_FIRMWARE_VERSION,
&firmware, sizeof(firmware));
if (error) {
dev_err(dev, "Failed to get firmware version, err: %d\n",
error);
return error;
}
/* get panel info */
error = ili210x_read_reg(client, REG_PANEL_INFO, &panel, sizeof(panel));
if (error) {
dev_err(dev, "Failed to get panel informations, err: %d\n",
error);
return error;
}
xmax = panel.finger_max.x_low | (panel.finger_max.x_high << 8);
ymax = panel.finger_max.y_low | (panel.finger_max.y_high << 8);
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
input = input_allocate_device();
if (!priv || !input) {
error = -ENOMEM;
goto err_free_mem;
}
priv->client = client;
priv->input = input;
priv->get_pendown_state = pdata->get_pendown_state;
priv->poll_period = pdata->poll_period ? : DEFAULT_POLL_PERIOD;
INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
/* Setup input device */
input->name = "ILI210x Touchscreen";
input->id.bustype = BUS_I2C;
input->dev.parent = dev;
__set_bit(EV_SYN, input->evbit);
__set_bit(EV_KEY, input->evbit);
__set_bit(EV_ABS, input->evbit);
__set_bit(BTN_TOUCH, input->keybit);
/* Single touch */
input_set_abs_params(input, ABS_X, 0, xmax, 0, 0);
input_set_abs_params(input, ABS_Y, 0, ymax, 0, 0);
/* Multi touch */
input_mt_init_slots(input, MAX_TOUCHES);
input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0);
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0);
input_set_drvdata(input, priv);
i2c_set_clientdata(client, priv);
error = request_irq(client->irq, ili210x_irq, pdata->irq_flags,
client->name, priv);
if (error) {
dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n",
error);
goto err_free_mem;
}
error = sysfs_create_group(&dev->kobj, &ili210x_attr_group);
if (error) {
dev_err(dev, "Unable to create sysfs attributes, err: %d\n",
error);
goto err_free_irq;
}
error = input_register_device(priv->input);
if (error) {
dev_err(dev, "Cannot regiser input device, err: %d\n", error);
goto err_remove_sysfs;
}
device_init_wakeup(&client->dev, 1);
dev_dbg(dev,
"ILI210x initialized (IRQ: %d), firmware version %d.%d.%d",
client->irq, firmware.id, firmware.major, firmware.minor);
return 0;
err_remove_sysfs:
sysfs_remove_group(&dev->kobj, &ili210x_attr_group);
err_free_irq:
free_irq(client->irq, priv);
err_free_mem:
input_free_device(input);
kfree(priv);
return error;
}
static int __devexit ili210x_i2c_remove(struct i2c_client *client)
{
struct ili210x *priv = i2c_get_clientdata(client);
sysfs_remove_group(&client->dev.kobj, &ili210x_attr_group);
free_irq(priv->client->irq, priv);
cancel_delayed_work_sync(&priv->dwork);
input_unregister_device(priv->input);
kfree(priv);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int ili210x_i2c_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
if (device_may_wakeup(&client->dev))
enable_irq_wake(client->irq);
return 0;
}
static int ili210x_i2c_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
if (device_may_wakeup(&client->dev))
disable_irq_wake(client->irq);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm,
ili210x_i2c_suspend, ili210x_i2c_resume);
static const struct i2c_device_id ili210x_i2c_id[] = {
{ "ili210x", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
static struct i2c_driver ili210x_ts_driver = {
.driver = {
.name = "ili210x_i2c",
.owner = THIS_MODULE,
.pm = &ili210x_i2c_pm,
},
.id_table = ili210x_i2c_id,
.probe = ili210x_i2c_probe,
.remove = __devexit_p(ili210x_i2c_remove),
};
module_i2c_driver(ili210x_ts_driver);
MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>");
MODULE_DESCRIPTION("ILI210X I2C Touchscreen Driver");
MODULE_LICENSE("GPL");
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.
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.
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