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
  ...
This commit is contained in:
Linus Torvalds 2012-03-22 20:20:18 -07:00
commit 7bfe0e66d5
101 changed files with 4091 additions and 706 deletions

View file

@ -0,0 +1,19 @@
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 >;

View file

@ -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;
};

View file

@ -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/

View file

@ -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>

View file

@ -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>

View file

@ -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;
};

View file

@ -1,15 +1,6 @@
#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

View file

@ -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 */

View file

@ -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);

View file

@ -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) },

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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.

View file

@ -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>");

View file

@ -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>");

View file

@ -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");

View file

@ -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");

View file

@ -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>");

View file

@ -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>");

View file

@ -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),
};

View file

@ -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

View file

@ -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");

View file

@ -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");

View file

@ -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)

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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>");

View file

@ -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>");

View file

@ -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");

View file

@ -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");

View file

@ -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);

View file

@ -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");

View file

@ -0,0 +1,169 @@
/*
* 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");

View file

@ -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");

View file

@ -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>");

View file

@ -1,5 +1,5 @@
/**
* 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;
int state;
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);
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),

View file

@ -0,0 +1,407 @@
/*
* MAX8997-haptic controller driver
*
* Copyright (C) 2012 Samsung Electronics
* Donggeun Kim <dg77.kim@samsung.com>
*
* This program is not provided / owned by Maxim Integrated Products.
*
* 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.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/pwm.h>
#include <linux/input.h>
#include <linux/mfd/max8997-private.h>
#include <linux/mfd/max8997.h>
#include <linux/regulator/consumer.h>
/* Haptic configuration 2 register */
#define MAX8997_MOTOR_TYPE_SHIFT 7
#define MAX8997_ENABLE_SHIFT 6
#define MAX8997_MODE_SHIFT 5
/* Haptic driver configuration register */
#define MAX8997_CYCLE_SHIFT 6
#define MAX8997_SIG_PERIOD_SHIFT 4
#define MAX8997_SIG_DUTY_SHIFT 2
#define MAX8997_PWM_DUTY_SHIFT 0
struct max8997_haptic {
struct device *dev;
struct i2c_client *client;
struct input_dev *input_dev;
struct regulator *regulator;
struct work_struct work;
struct mutex mutex;
bool enabled;
unsigned int level;
struct pwm_device *pwm;
unsigned int pwm_period;
enum max8997_haptic_pwm_divisor pwm_divisor;
enum max8997_haptic_motor_type type;
enum max8997_haptic_pulse_mode mode;
unsigned int internal_mode_pattern;
unsigned int pattern_cycle;
unsigned int pattern_signal_period;
};
static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip)
{
int ret = 0;
if (chip->mode == MAX8997_EXTERNAL_MODE) {
unsigned int duty = chip->pwm_period * chip->level / 100;
ret = pwm_config(chip->pwm, duty, chip->pwm_period);
} else {
int i;
u8 duty_index = 0;
for (i = 0; i <= 64; i++) {
if (chip->level <= i * 100 / 64) {
duty_index = i;
break;
}
}
switch (chip->internal_mode_pattern) {
case 0:
max8997_write_reg(chip->client,
MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index);
break;
case 1:
max8997_write_reg(chip->client,
MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index);
break;
case 2:
max8997_write_reg(chip->client,
MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index);
break;
case 3:
max8997_write_reg(chip->client,
MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index);
break;
default:
break;
}
}
return ret;
}
static void max8997_haptic_configure(struct max8997_haptic *chip)
{
u8 value;
value = chip->type << MAX8997_MOTOR_TYPE_SHIFT |
chip->enabled << MAX8997_ENABLE_SHIFT |
chip->mode << MAX8997_MODE_SHIFT | chip->pwm_divisor;
max8997_write_reg(chip->client, MAX8997_HAPTIC_REG_CONF2, value);
if (chip->mode == MAX8997_INTERNAL_MODE && chip->enabled) {
value = chip->internal_mode_pattern << MAX8997_CYCLE_SHIFT |
chip->internal_mode_pattern << MAX8997_SIG_PERIOD_SHIFT |
chip->internal_mode_pattern << MAX8997_SIG_DUTY_SHIFT |
chip->internal_mode_pattern << MAX8997_PWM_DUTY_SHIFT;
max8997_write_reg(chip->client,
MAX8997_HAPTIC_REG_DRVCONF, value);
switch (chip->internal_mode_pattern) {
case 0:
value = chip->pattern_cycle << 4;
max8997_write_reg(chip->client,
MAX8997_HAPTIC_REG_CYCLECONF1, value);
value = chip->pattern_signal_period;
max8997_write_reg(chip->client,
MAX8997_HAPTIC_REG_SIGCONF1, value);
break;
case 1:
value = chip->pattern_cycle;
max8997_write_reg(chip->client,
MAX8997_HAPTIC_REG_CYCLECONF1, value);
value = chip->pattern_signal_period;
max8997_write_reg(chip->client,
MAX8997_HAPTIC_REG_SIGCONF2, value);
break;
case 2:
value = chip->pattern_cycle << 4;
max8997_write_reg(chip->client,
MAX8997_HAPTIC_REG_CYCLECONF2, value);
value = chip->pattern_signal_period;
max8997_write_reg(chip->client,
MAX8997_HAPTIC_REG_SIGCONF3, value);
break;
case 3:
value = chip->pattern_cycle;
max8997_write_reg(chip->client,
MAX8997_HAPTIC_REG_CYCLECONF2, value);
value = chip->pattern_signal_period;
max8997_write_reg(chip->client,
MAX8997_HAPTIC_REG_SIGCONF4, value);
break;
default:
break;
}
}
}
static void max8997_haptic_enable(struct max8997_haptic *chip)
{
int error;
mutex_lock(&chip->mutex);
error = max8997_haptic_set_duty_cycle(chip);
if (error) {
dev_err(chip->dev, "set_pwm_cycle failed, error: %d\n", error);
goto out;
}
if (!chip->enabled) {
chip->enabled = true;
regulator_enable(chip->regulator);
max8997_haptic_configure(chip);
if (chip->mode == MAX8997_EXTERNAL_MODE)
pwm_enable(chip->pwm);
}
out:
mutex_unlock(&chip->mutex);
}
static void max8997_haptic_disable(struct max8997_haptic *chip)
{
mutex_lock(&chip->mutex);
if (chip->enabled) {
chip->enabled = false;
max8997_haptic_configure(chip);
if (chip->mode == MAX8997_EXTERNAL_MODE)
pwm_disable(chip->pwm);
regulator_disable(chip->regulator);
}
mutex_unlock(&chip->mutex);
}
static void max8997_haptic_play_effect_work(struct work_struct *work)
{
struct max8997_haptic *chip =
container_of(work, struct max8997_haptic, work);
if (chip->level)
max8997_haptic_enable(chip);
else
max8997_haptic_disable(chip);
}
static int max8997_haptic_play_effect(struct input_dev *dev, void *data,
struct ff_effect *effect)
{
struct max8997_haptic *chip = input_get_drvdata(dev);
chip->level = effect->u.rumble.strong_magnitude;
if (!chip->level)
chip->level = effect->u.rumble.weak_magnitude;
schedule_work(&chip->work);
return 0;
}
static void max8997_haptic_close(struct input_dev *dev)
{
struct max8997_haptic *chip = input_get_drvdata(dev);
cancel_work_sync(&chip->work);
max8997_haptic_disable(chip);
}
static int __devinit max8997_haptic_probe(struct platform_device *pdev)
{
struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
const struct max8997_platform_data *pdata =
dev_get_platdata(iodev->dev);
const struct max8997_haptic_platform_data *haptic_pdata =
pdata->haptic_pdata;
struct max8997_haptic *chip;
struct input_dev *input_dev;
int error;
if (!haptic_pdata) {
dev_err(&pdev->dev, "no haptic platform data\n");
return -EINVAL;
}
chip = kzalloc(sizeof(struct max8997_haptic), GFP_KERNEL);
input_dev = input_allocate_device();
if (!chip || !input_dev) {
dev_err(&pdev->dev, "unable to allocate memory\n");
error = -ENOMEM;
goto err_free_mem;
}
INIT_WORK(&chip->work, max8997_haptic_play_effect_work);
mutex_init(&chip->mutex);
chip->client = iodev->haptic;
chip->dev = &pdev->dev;
chip->input_dev = input_dev;
chip->pwm_period = haptic_pdata->pwm_period;
chip->type = haptic_pdata->type;
chip->mode = haptic_pdata->mode;
chip->pwm_divisor = haptic_pdata->pwm_divisor;
switch (chip->mode) {
case MAX8997_INTERNAL_MODE:
chip->internal_mode_pattern =
haptic_pdata->internal_mode_pattern;
chip->pattern_cycle = haptic_pdata->pattern_cycle;
chip->pattern_signal_period =
haptic_pdata->pattern_signal_period;
break;
case MAX8997_EXTERNAL_MODE:
chip->pwm = pwm_request(haptic_pdata->pwm_channel_id,
"max8997-haptic");
if (IS_ERR(chip->pwm)) {
error = PTR_ERR(chip->pwm);
dev_err(&pdev->dev,
"unable to request PWM for haptic, error: %d\n",
error);
goto err_free_mem;
}
break;
default:
dev_err(&pdev->dev,
"Invalid chip mode specified (%d)\n", chip->mode);
error = -EINVAL;
goto err_free_mem;
}
chip->regulator = regulator_get(&pdev->dev, "inmotor");
if (IS_ERR(chip->regulator)) {
error = PTR_ERR(chip->regulator);
dev_err(&pdev->dev,
"unable to get regulator, error: %d\n",
error);
goto err_free_pwm;
}
input_dev->name = "max8997-haptic";
input_dev->id.version = 1;
input_dev->dev.parent = &pdev->dev;
input_dev->close = max8997_haptic_close;
input_set_drvdata(input_dev, chip);
input_set_capability(input_dev, EV_FF, FF_RUMBLE);
error = input_ff_create_memless(input_dev, NULL,
max8997_haptic_play_effect);
if (error) {
dev_err(&pdev->dev,
"unable to create FF device, error: %d\n",
error);
goto err_put_regulator;
}
error = input_register_device(input_dev);
if (error) {
dev_err(&pdev->dev,
"unable to register input device, error: %d\n",
error);
goto err_destroy_ff;
}
platform_set_drvdata(pdev, chip);
return 0;
err_destroy_ff:
input_ff_destroy(input_dev);
err_put_regulator:
regulator_put(chip->regulator);
err_free_pwm:
if (chip->mode == MAX8997_EXTERNAL_MODE)
pwm_free(chip->pwm);
err_free_mem:
input_free_device(input_dev);
kfree(chip);
return error;
}
static int __devexit max8997_haptic_remove(struct platform_device *pdev)
{
struct max8997_haptic *chip = platform_get_drvdata(pdev);
input_unregister_device(chip->input_dev);
regulator_put(chip->regulator);
if (chip->mode == MAX8997_EXTERNAL_MODE)
pwm_free(chip->pwm);
kfree(chip);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int max8997_haptic_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct max8997_haptic *chip = platform_get_drvdata(pdev);
max8997_haptic_disable(chip);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(max8997_haptic_pm_ops, max8997_haptic_suspend, NULL);
static const struct platform_device_id max8997_haptic_id[] = {
{ "max8997-haptic", 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, max8997_haptic_id);
static struct platform_driver max8997_haptic_driver = {
.driver = {
.name = "max8997-haptic",
.owner = THIS_MODULE,
.pm = &max8997_haptic_pm_ops,
},
.probe = max8997_haptic_probe,
.remove = __devexit_p(max8997_haptic_remove),
.id_table = max8997_haptic_id,
};
module_platform_driver(max8997_haptic_driver);
MODULE_ALIAS("platform:max8997-haptic");
MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
MODULE_DESCRIPTION("max8997_haptic driver");
MODULE_LICENSE("GPL");

View file

@ -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");

View file

@ -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");

View file

@ -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");

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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");

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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");

View file

@ -0,0 +1,557 @@
/*
* USB Synaptics device driver
*
* Copyright (c) 2002 Rob Miller (rob@inpharmatica . co . uk)
* Copyright (c) 2003 Ron Lee (ron@debian.org)
* cPad driver for kernel 2.4
*
* Copyright (c) 2004 Jan Steinhoff (cpad@jan-steinhoff . de)
* Copyright (c) 2004 Ron Lee (ron@debian.org)
* rewritten for kernel 2.6
*
* cPad display character device part is not included. It can be found at
* http://jan-steinhoff.de/linux/synaptics-usb.html
*
* Bases on: usb_skeleton.c v2.2 by Greg Kroah-Hartman
* drivers/hid/usbhid/usbmouse.c by Vojtech Pavlik
* drivers/input/mouse/synaptics.c by Peter Osterlund
*
* 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.
*
* Trademarks are the property of their respective owners.
*/
/*
* There are three different types of Synaptics USB devices: Touchpads,
* touchsticks (or trackpoints), and touchscreens. Touchpads are well supported
* by this driver, touchstick support has not been tested much yet, and
* touchscreens have not been tested at all.
*
* Up to three alternate settings are possible:
* setting 0: one int endpoint for relative movement (used by usbhid.ko)
* setting 1: one int endpoint for absolute finger position
* setting 2 (cPad only): one int endpoint for absolute finger position and
* two bulk endpoints for the display (in/out)
* This driver uses setting 1.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/usb.h>
#include <linux/input.h>
#include <linux/usb/input.h>
#define USB_VENDOR_ID_SYNAPTICS 0x06cb
#define USB_DEVICE_ID_SYNAPTICS_TP 0x0001 /* Synaptics USB TouchPad */
#define USB_DEVICE_ID_SYNAPTICS_INT_TP 0x0002 /* Integrated USB TouchPad */
#define USB_DEVICE_ID_SYNAPTICS_CPAD 0x0003 /* Synaptics cPad */
#define USB_DEVICE_ID_SYNAPTICS_TS 0x0006 /* Synaptics TouchScreen */
#define USB_DEVICE_ID_SYNAPTICS_STICK 0x0007 /* Synaptics USB Styk */
#define USB_DEVICE_ID_SYNAPTICS_WP 0x0008 /* Synaptics USB WheelPad */
#define USB_DEVICE_ID_SYNAPTICS_COMP_TP 0x0009 /* Composite USB TouchPad */
#define USB_DEVICE_ID_SYNAPTICS_WTP 0x0010 /* Wireless TouchPad */
#define USB_DEVICE_ID_SYNAPTICS_DPAD 0x0013 /* DisplayPad */
#define SYNUSB_TOUCHPAD (1 << 0)
#define SYNUSB_STICK (1 << 1)
#define SYNUSB_TOUCHSCREEN (1 << 2)
#define SYNUSB_AUXDISPLAY (1 << 3) /* For cPad */
#define SYNUSB_COMBO (1 << 4) /* Composite device (TP + stick) */
#define SYNUSB_IO_ALWAYS (1 << 5)
#define USB_DEVICE_SYNAPTICS(prod, kind) \
USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, \
USB_DEVICE_ID_SYNAPTICS_##prod), \
.driver_info = (kind),
#define SYNUSB_RECV_SIZE 8
#define XMIN_NOMINAL 1472
#define XMAX_NOMINAL 5472
#define YMIN_NOMINAL 1408
#define YMAX_NOMINAL 4448
struct synusb {
struct usb_device *udev;
struct usb_interface *intf;
struct urb *urb;
unsigned char *data;
/* input device related data structures */
struct input_dev *input;
char name[128];
char phys[64];
/* characteristics of the device */
unsigned long flags;
};
static void synusb_report_buttons(struct synusb *synusb)
{
struct input_dev *input_dev = synusb->input;
input_report_key(input_dev, BTN_LEFT, synusb->data[1] & 0x04);
input_report_key(input_dev, BTN_RIGHT, synusb->data[1] & 0x01);
input_report_key(input_dev, BTN_MIDDLE, synusb->data[1] & 0x02);
}
static void synusb_report_stick(struct synusb *synusb)
{
struct input_dev *input_dev = synusb->input;
int x, y;
unsigned int pressure;
pressure = synusb->data[6];
x = (s16)(be16_to_cpup((__be16 *)&synusb->data[2]) << 3) >> 7;
y = (s16)(be16_to_cpup((__be16 *)&synusb->data[4]) << 3) >> 7;
if (pressure > 0) {
input_report_rel(input_dev, REL_X, x);
input_report_rel(input_dev, REL_Y, -y);
}
input_report_abs(input_dev, ABS_PRESSURE, pressure);
synusb_report_buttons(synusb);
input_sync(input_dev);
}
static void synusb_report_touchpad(struct synusb *synusb)
{
struct input_dev *input_dev = synusb->input;
unsigned int num_fingers, tool_width;
unsigned int x, y;
unsigned int pressure, w;
pressure = synusb->data[6];
x = be16_to_cpup((__be16 *)&synusb->data[2]);
y = be16_to_cpup((__be16 *)&synusb->data[4]);
w = synusb->data[0] & 0x0f;
if (pressure > 0) {
num_fingers = 1;
tool_width = 5;
switch (w) {
case 0 ... 1:
num_fingers = 2 + w;
break;
case 2: /* pen, pretend its a finger */
break;
case 4 ... 15:
tool_width = w;
break;
}
} else {
num_fingers = 0;
tool_width = 0;
}
/*
* Post events
* BTN_TOUCH has to be first as mousedev relies on it when doing
* absolute -> relative conversion
*/
if (pressure > 30)
input_report_key(input_dev, BTN_TOUCH, 1);
if (pressure < 25)
input_report_key(input_dev, BTN_TOUCH, 0);
if (num_fingers > 0) {
input_report_abs(input_dev, ABS_X, x);
input_report_abs(input_dev, ABS_Y,
YMAX_NOMINAL + YMIN_NOMINAL - y);
}
input_report_abs(input_dev, ABS_PRESSURE, pressure);
input_report_abs(input_dev, ABS_TOOL_WIDTH, tool_width);
input_report_key(input_dev, BTN_TOOL_FINGER, num_fingers == 1);
input_report_key(input_dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
input_report_key(input_dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
synusb_report_buttons(synusb);
if (synusb->flags & SYNUSB_AUXDISPLAY)
input_report_key(input_dev, BTN_MIDDLE, synusb->data[1] & 0x08);
input_sync(input_dev);
}
static void synusb_irq(struct urb *urb)
{
struct synusb *synusb = urb->context;
int error;
/* Check our status in case we need to bail out early. */
switch (urb->status) {
case 0:
usb_mark_last_busy(synusb->udev);
break;
/* Device went away so don't keep trying to read from it. */
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
return;
default:
goto resubmit;
break;
}
if (synusb->flags & SYNUSB_STICK)
synusb_report_stick(synusb);
else
synusb_report_touchpad(synusb);
resubmit:
error = usb_submit_urb(urb, GFP_ATOMIC);
if (error && error != -EPERM)
dev_err(&synusb->intf->dev,
"%s - usb_submit_urb failed with result: %d",
__func__, error);
}
static struct usb_endpoint_descriptor *
synusb_get_in_endpoint(struct usb_host_interface *iface)
{
struct usb_endpoint_descriptor *endpoint;
int i;
for (i = 0; i < iface->desc.bNumEndpoints; ++i) {
endpoint = &iface->endpoint[i].desc;
if (usb_endpoint_is_int_in(endpoint)) {
/* we found our interrupt in endpoint */
return endpoint;
}
}
return NULL;
}
static int synusb_open(struct input_dev *dev)
{
struct synusb *synusb = input_get_drvdata(dev);
int retval;
retval = usb_autopm_get_interface(synusb->intf);
if (retval) {
dev_err(&synusb->intf->dev,
"%s - usb_autopm_get_interface failed, error: %d\n",
__func__, retval);
return retval;
}
retval = usb_submit_urb(synusb->urb, GFP_KERNEL);
if (retval) {
dev_err(&synusb->intf->dev,
"%s - usb_submit_urb failed, error: %d\n",
__func__, retval);
retval = -EIO;
goto out;
}
synusb->intf->needs_remote_wakeup = 1;
out:
usb_autopm_put_interface(synusb->intf);
return retval;
}
static void synusb_close(struct input_dev *dev)
{
struct synusb *synusb = input_get_drvdata(dev);
int autopm_error;
autopm_error = usb_autopm_get_interface(synusb->intf);
usb_kill_urb(synusb->urb);
synusb->intf->needs_remote_wakeup = 0;
if (!autopm_error)
usb_autopm_put_interface(synusb->intf);
}
static int synusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_endpoint_descriptor *ep;
struct synusb *synusb;
struct input_dev *input_dev;
unsigned int intf_num = intf->cur_altsetting->desc.bInterfaceNumber;
unsigned int altsetting = min(intf->num_altsetting, 1U);
int error;
error = usb_set_interface(udev, intf_num, altsetting);
if (error) {
dev_err(&udev->dev,
"Can not set alternate setting to %i, error: %i",
altsetting, error);
return error;
}
ep = synusb_get_in_endpoint(intf->cur_altsetting);
if (!ep)
return -ENODEV;
synusb = kzalloc(sizeof(*synusb), GFP_KERNEL);
input_dev = input_allocate_device();
if (!synusb || !input_dev) {
error = -ENOMEM;
goto err_free_mem;
}
synusb->udev = udev;
synusb->intf = intf;
synusb->input = input_dev;
synusb->flags = id->driver_info;
if (synusb->flags & SYNUSB_COMBO) {
/*
* This is a combo device, we need to set proper
* capability, depending on the interface.
*/
synusb->flags |= intf_num == 1 ?
SYNUSB_STICK : SYNUSB_TOUCHPAD;
}
synusb->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!synusb->urb) {
error = -ENOMEM;
goto err_free_mem;
}
synusb->data = usb_alloc_coherent(udev, SYNUSB_RECV_SIZE, GFP_KERNEL,
&synusb->urb->transfer_dma);
if (!synusb->data) {
error = -ENOMEM;
goto err_free_urb;
}
usb_fill_int_urb(synusb->urb, udev,
usb_rcvintpipe(udev, ep->bEndpointAddress),
synusb->data, SYNUSB_RECV_SIZE,
synusb_irq, synusb,
ep->bInterval);
synusb->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
if (udev->manufacturer)
strlcpy(synusb->name, udev->manufacturer,
sizeof(synusb->name));
if (udev->product) {
if (udev->manufacturer)
strlcat(synusb->name, " ", sizeof(synusb->name));
strlcat(synusb->name, udev->product, sizeof(synusb->name));
}
if (!strlen(synusb->name))
snprintf(synusb->name, sizeof(synusb->name),
"USB Synaptics Device %04x:%04x",
le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct));
if (synusb->flags & SYNUSB_STICK)
strlcat(synusb->name, " (Stick) ", sizeof(synusb->name));
usb_make_path(udev, synusb->phys, sizeof(synusb->phys));
strlcat(synusb->phys, "/input0", sizeof(synusb->phys));
input_dev->name = synusb->name;
input_dev->phys = synusb->phys;
usb_to_input_id(udev, &input_dev->id);
input_dev->dev.parent = &synusb->intf->dev;
if (!(synusb->flags & SYNUSB_IO_ALWAYS)) {
input_dev->open = synusb_open;
input_dev->close = synusb_close;
}
input_set_drvdata(input_dev, synusb);
__set_bit(EV_ABS, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
if (synusb->flags & SYNUSB_STICK) {
__set_bit(EV_REL, input_dev->evbit);
__set_bit(REL_X, input_dev->relbit);
__set_bit(REL_Y, input_dev->relbit);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, 127, 0, 0);
} else {
input_set_abs_params(input_dev, ABS_X,
XMIN_NOMINAL, XMAX_NOMINAL, 0, 0);
input_set_abs_params(input_dev, ABS_Y,
YMIN_NOMINAL, YMAX_NOMINAL, 0, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0);
input_set_abs_params(input_dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
__set_bit(BTN_TOUCH, input_dev->keybit);
__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
}
__set_bit(BTN_LEFT, input_dev->keybit);
__set_bit(BTN_RIGHT, input_dev->keybit);
__set_bit(BTN_MIDDLE, input_dev->keybit);
usb_set_intfdata(intf, synusb);
if (synusb->flags & SYNUSB_IO_ALWAYS) {
error = synusb_open(input_dev);
if (error)
goto err_free_dma;
}
error = input_register_device(input_dev);
if (error) {
dev_err(&udev->dev,
"Failed to register input device, error %d\n",
error);
goto err_stop_io;
}
return 0;
err_stop_io:
if (synusb->flags & SYNUSB_IO_ALWAYS)
synusb_close(synusb->input);
err_free_dma:
usb_free_coherent(udev, SYNUSB_RECV_SIZE, synusb->data,
synusb->urb->transfer_dma);
err_free_urb:
usb_free_urb(synusb->urb);
err_free_mem:
input_free_device(input_dev);
kfree(synusb);
usb_set_intfdata(intf, NULL);
return error;
}
static void synusb_disconnect(struct usb_interface *intf)
{
struct synusb *synusb = usb_get_intfdata(intf);
struct usb_device *udev = interface_to_usbdev(intf);
if (synusb->flags & SYNUSB_IO_ALWAYS)
synusb_close(synusb->input);
input_unregister_device(synusb->input);
usb_free_coherent(udev, SYNUSB_RECV_SIZE, synusb->data,
synusb->urb->transfer_dma);
usb_free_urb(synusb->urb);
kfree(synusb);
usb_set_intfdata(intf, NULL);
}
static int synusb_suspend(struct usb_interface *intf, pm_message_t message)
{
struct synusb *synusb = usb_get_intfdata(intf);
struct input_dev *input_dev = synusb->input;
mutex_lock(&input_dev->mutex);
usb_kill_urb(synusb->urb);
mutex_unlock(&input_dev->mutex);
return 0;
}
static int synusb_resume(struct usb_interface *intf)
{
struct synusb *synusb = usb_get_intfdata(intf);
struct input_dev *input_dev = synusb->input;
int retval = 0;
mutex_lock(&input_dev->mutex);
if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) &&
usb_submit_urb(synusb->urb, GFP_NOIO) < 0) {
retval = -EIO;
}
mutex_unlock(&input_dev->mutex);
return retval;
}
static int synusb_pre_reset(struct usb_interface *intf)
{
struct synusb *synusb = usb_get_intfdata(intf);
struct input_dev *input_dev = synusb->input;
mutex_lock(&input_dev->mutex);
usb_kill_urb(synusb->urb);
return 0;
}
static int synusb_post_reset(struct usb_interface *intf)
{
struct synusb *synusb = usb_get_intfdata(intf);
struct input_dev *input_dev = synusb->input;
int retval = 0;
if ((input_dev->users || (synusb->flags & SYNUSB_IO_ALWAYS)) &&
usb_submit_urb(synusb->urb, GFP_NOIO) < 0) {
retval = -EIO;
}
mutex_unlock(&input_dev->mutex);
return retval;
}
static int synusb_reset_resume(struct usb_interface *intf)
{
return synusb_resume(intf);
}
static struct usb_device_id synusb_idtable[] = {
{ USB_DEVICE_SYNAPTICS(TP, SYNUSB_TOUCHPAD) },
{ USB_DEVICE_SYNAPTICS(INT_TP, SYNUSB_TOUCHPAD) },
{ USB_DEVICE_SYNAPTICS(CPAD,
SYNUSB_TOUCHPAD | SYNUSB_AUXDISPLAY | SYNUSB_IO_ALWAYS) },
{ USB_DEVICE_SYNAPTICS(TS, SYNUSB_TOUCHSCREEN) },
{ USB_DEVICE_SYNAPTICS(STICK, SYNUSB_STICK) },
{ USB_DEVICE_SYNAPTICS(WP, SYNUSB_TOUCHPAD) },
{ USB_DEVICE_SYNAPTICS(COMP_TP, SYNUSB_COMBO) },
{ USB_DEVICE_SYNAPTICS(WTP, SYNUSB_TOUCHPAD) },
{ USB_DEVICE_SYNAPTICS(DPAD, SYNUSB_TOUCHPAD) },
{ }
};
MODULE_DEVICE_TABLE(usb, synusb_idtable);
static struct usb_driver synusb_driver = {
.name = "synaptics_usb",
.probe = synusb_probe,
.disconnect = synusb_disconnect,
.id_table = synusb_idtable,
.suspend = synusb_suspend,
.resume = synusb_resume,
.pre_reset = synusb_pre_reset,
.post_reset = synusb_post_reset,
.reset_resume = synusb_reset_resume,
.supports_autosuspend = 1,
};
module_usb_driver(synusb_driver);
MODULE_AUTHOR("Rob Miller <rob@inpharmatica.co.uk>, "
"Ron Lee <ron@debian.org>, "
"Jan Steinhoff <cpad@jan-steinhoff.de>");
MODULE_DESCRIPTION("Synaptics USB device driver");
MODULE_LICENSE("GPL");

87
drivers/input/of_keymap.c Normal file
View file

@ -0,0 +1,87 @@
/*
* 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);

View file

@ -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);

View file

@ -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)

View file

@ -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;
struct q40kbd *q40kbd;
struct serio *port;
int error;
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));
q40kbd = kzalloc(sizeof(struct q40kbd), GFP_KERNEL);
port = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!q40kbd || !port) {
error = -ENOMEM;
goto err_free_mem;
}
serio_register_port(q40kbd_port);
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);
}

View file

@ -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 =

View file

@ -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)
return wacom_tpc_single_touch(wacom, len);
else if (data[0] == WACOM_REPORT_TPC2FG)
return wacom_tpc_mt_touch(wacom);
else if (data[0] == WACOM_REPORT_PENABLED)
return wacom_tpc_pen(wacom);
switch (len) {
case WACOM_PKGLEN_TPC1FG:
return wacom_tpc_single_touch(wacom, len);
case WACOM_PKGLEN_TPC2FG:
return wacom_tpc_mt_touch(wacom);
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);

View file

@ -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

View file

@ -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

View file

@ -16,8 +16,11 @@ obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o
obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
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_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

View file

@ -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");

View file

@ -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");

View file

@ -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");

View file

@ -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");

View file

@ -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",
.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)

View file

@ -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>");

View file

@ -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");

View file

@ -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>");

View file

@ -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");

View file

@ -0,0 +1,625 @@
/*
* Core Source 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>
*
*/
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include "cyttsp_core.h"
/* Bootloader number of command keys */
#define CY_NUM_BL_KEYS 8
/* helpers */
#define GET_NUM_TOUCHES(x) ((x) & 0x0F)
#define IS_LARGE_AREA(x) (((x) & 0x10) >> 4)
#define IS_BAD_PKT(x) ((x) & 0x20)
#define IS_VALID_APP(x) ((x) & 0x01)
#define IS_OPERATIONAL_ERR(x) ((x) & 0x3F)
#define GET_HSTMODE(reg) (((reg) & 0x70) >> 4)
#define GET_BOOTLOADERMODE(reg) (((reg) & 0x10) >> 4)
#define CY_REG_BASE 0x00
#define CY_REG_ACT_DIST 0x1E
#define CY_REG_ACT_INTRVL 0x1D
#define CY_REG_TCH_TMOUT (CY_REG_ACT_INTRVL + 1)
#define CY_REG_LP_INTRVL (CY_REG_TCH_TMOUT + 1)
#define CY_MAXZ 255
#define CY_DELAY_DFLT 20 /* ms */
#define CY_DELAY_MAX 500
#define CY_ACT_DIST_DFLT 0xF8
#define CY_HNDSHK_BIT 0x80
/* device mode bits */
#define CY_OPERATE_MODE 0x00
#define CY_SYSINFO_MODE 0x10
/* power mode select bits */
#define CY_SOFT_RESET_MODE 0x01 /* return to Bootloader mode */
#define CY_DEEP_SLEEP_MODE 0x02
#define CY_LOW_POWER_MODE 0x04
/* Slots management */
#define CY_MAX_FINGER 4
#define CY_MAX_ID 16
static const u8 bl_command[] = {
0x00, /* file offset */
0xFF, /* command */
0xA5, /* exit bootloader command */
0, 1, 2, 3, 4, 5, 6, 7 /* default keys */
};
static int ttsp_read_block_data(struct cyttsp *ts, u8 command,
u8 length, void *buf)
{
int error;
int tries;
for (tries = 0; tries < CY_NUM_RETRY; tries++) {
error = ts->bus_ops->read(ts, command, length, buf);
if (!error)
return 0;
msleep(CY_DELAY_DFLT);
}
return -EIO;
}
static int ttsp_write_block_data(struct cyttsp *ts, u8 command,
u8 length, void *buf)
{
int error;
int tries;
for (tries = 0; tries < CY_NUM_RETRY; tries++) {
error = ts->bus_ops->write(ts, command, length, buf);
if (!error)
return 0;
msleep(CY_DELAY_DFLT);
}
return -EIO;
}
static int ttsp_send_command(struct cyttsp *ts, u8 cmd)
{
return ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd);
}
static int cyttsp_load_bl_regs(struct cyttsp *ts)
{
memset(&ts->bl_data, 0, sizeof(ts->bl_data));
ts->bl_data.bl_status = 0x10;
return ttsp_read_block_data(ts, CY_REG_BASE,
sizeof(ts->bl_data), &ts->bl_data);
}
static int cyttsp_exit_bl_mode(struct cyttsp *ts)
{
int error;
u8 bl_cmd[sizeof(bl_command)];
memcpy(bl_cmd, bl_command, sizeof(bl_command));
if (ts->pdata->bl_keys)
memcpy(&bl_cmd[sizeof(bl_command) - CY_NUM_BL_KEYS],
ts->pdata->bl_keys, sizeof(bl_command));
error = ttsp_write_block_data(ts, CY_REG_BASE,
sizeof(bl_cmd), bl_cmd);
if (error)
return error;
/* wait for TTSP Device to complete the operation */
msleep(CY_DELAY_DFLT);
error = cyttsp_load_bl_regs(ts);
if (error)
return error;
if (GET_BOOTLOADERMODE(ts->bl_data.bl_status))
return -EIO;
return 0;
}
static int cyttsp_set_operational_mode(struct cyttsp *ts)
{
int error;
error = ttsp_send_command(ts, CY_OPERATE_MODE);
if (error)
return error;
/* wait for TTSP Device to complete switch to Operational mode */
error = ttsp_read_block_data(ts, CY_REG_BASE,
sizeof(ts->xy_data), &ts->xy_data);
if (error)
return error;
return ts->xy_data.act_dist == CY_ACT_DIST_DFLT ? -EIO : 0;
}
static int cyttsp_set_sysinfo_mode(struct cyttsp *ts)
{
int error;
memset(&ts->sysinfo_data, 0, sizeof(ts->sysinfo_data));
/* switch to sysinfo mode */
error = ttsp_send_command(ts, CY_SYSINFO_MODE);
if (error)
return error;
/* read sysinfo registers */
msleep(CY_DELAY_DFLT);
error = ttsp_read_block_data(ts, CY_REG_BASE, sizeof(ts->sysinfo_data),
&ts->sysinfo_data);
if (error)
return error;
if (!ts->sysinfo_data.tts_verh && !ts->sysinfo_data.tts_verl)
return -EIO;
return 0;
}
static int cyttsp_set_sysinfo_regs(struct cyttsp *ts)
{
int retval = 0;
if (ts->pdata->act_intrvl != CY_ACT_INTRVL_DFLT ||
ts->pdata->tch_tmout != CY_TCH_TMOUT_DFLT ||
ts->pdata->lp_intrvl != CY_LP_INTRVL_DFLT) {
u8 intrvl_ray[] = {
ts->pdata->act_intrvl,
ts->pdata->tch_tmout,
ts->pdata->lp_intrvl
};
/* set intrvl registers */
retval = ttsp_write_block_data(ts, CY_REG_ACT_INTRVL,
sizeof(intrvl_ray), intrvl_ray);
msleep(CY_DELAY_DFLT);
}
return retval;
}
static int cyttsp_soft_reset(struct cyttsp *ts)
{
unsigned long timeout;
int retval;
/* wait for interrupt to set ready completion */
INIT_COMPLETION(ts->bl_ready);
ts->state = CY_BL_STATE;
enable_irq(ts->irq);
retval = ttsp_send_command(ts, CY_SOFT_RESET_MODE);
if (retval)
goto out;
timeout = wait_for_completion_timeout(&ts->bl_ready,
msecs_to_jiffies(CY_DELAY_DFLT * CY_DELAY_MAX));
retval = timeout ? 0 : -EIO;
out:
ts->state = CY_IDLE_STATE;
disable_irq(ts->irq);
return retval;
}
static int cyttsp_act_dist_setup(struct cyttsp *ts)
{
u8 act_dist_setup = ts->pdata->act_dist;
/* Init gesture; active distance setup */
return ttsp_write_block_data(ts, CY_REG_ACT_DIST,
sizeof(act_dist_setup), &act_dist_setup);
}
static void cyttsp_extract_track_ids(struct cyttsp_xydata *xy_data, int *ids)
{
ids[0] = xy_data->touch12_id >> 4;
ids[1] = xy_data->touch12_id & 0xF;
ids[2] = xy_data->touch34_id >> 4;
ids[3] = xy_data->touch34_id & 0xF;
}
static const struct cyttsp_tch *cyttsp_get_tch(struct cyttsp_xydata *xy_data,
int idx)
{
switch (idx) {
case 0:
return &xy_data->tch1;
case 1:
return &xy_data->tch2;
case 2:
return &xy_data->tch3;
case 3:
return &xy_data->tch4;
default:
return NULL;
}
}
static void cyttsp_report_tchdata(struct cyttsp *ts)
{
struct cyttsp_xydata *xy_data = &ts->xy_data;
struct input_dev *input = ts->input;
int num_tch = GET_NUM_TOUCHES(xy_data->tt_stat);
const struct cyttsp_tch *tch;
int ids[CY_MAX_ID];
int i;
DECLARE_BITMAP(used, CY_MAX_ID);
if (IS_LARGE_AREA(xy_data->tt_stat) == 1) {
/* terminate all active tracks */
num_tch = 0;
dev_dbg(ts->dev, "%s: Large area detected\n", __func__);
} else if (num_tch > CY_MAX_FINGER) {
/* terminate all active tracks */
num_tch = 0;
dev_dbg(ts->dev, "%s: Num touch error detected\n", __func__);
} else if (IS_BAD_PKT(xy_data->tt_mode)) {
/* terminate all active tracks */
num_tch = 0;
dev_dbg(ts->dev, "%s: Invalid buffer detected\n", __func__);
}
cyttsp_extract_track_ids(xy_data, ids);
bitmap_zero(used, CY_MAX_ID);
for (i = 0; i < num_tch; i++) {
tch = cyttsp_get_tch(xy_data, i);
input_mt_slot(input, ids[i]);
input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
input_report_abs(input, ABS_MT_POSITION_X, be16_to_cpu(tch->x));
input_report_abs(input, ABS_MT_POSITION_Y, be16_to_cpu(tch->y));
input_report_abs(input, ABS_MT_TOUCH_MAJOR, tch->z);
__set_bit(ids[i], used);
}
for (i = 0; i < CY_MAX_ID; i++) {
if (test_bit(i, used))
continue;
input_mt_slot(input, i);
input_mt_report_slot_state(input, MT_TOOL_FINGER, false);
}
input_sync(input);
}
static irqreturn_t cyttsp_irq(int irq, void *handle)
{
struct cyttsp *ts = handle;
int error;
if (unlikely(ts->state == CY_BL_STATE)) {
complete(&ts->bl_ready);
goto out;
}
/* Get touch data from CYTTSP device */
error = ttsp_read_block_data(ts, CY_REG_BASE,
sizeof(struct cyttsp_xydata), &ts->xy_data);
if (error)
goto out;
/* provide flow control handshake */
if (ts->pdata->use_hndshk) {
error = ttsp_send_command(ts,
ts->xy_data.hst_mode ^ CY_HNDSHK_BIT);
if (error)
goto out;
}
if (unlikely(ts->state == CY_IDLE_STATE))
goto out;
if (GET_BOOTLOADERMODE(ts->xy_data.tt_mode)) {
/*
* TTSP device has reset back to bootloader mode.
* Restore to operational mode.
*/
error = cyttsp_exit_bl_mode(ts);
if (error) {
dev_err(ts->dev,
"Could not return to operational mode, err: %d\n",
error);
ts->state = CY_IDLE_STATE;
}
} else {
cyttsp_report_tchdata(ts);
}
out:
return IRQ_HANDLED;
}
static int cyttsp_power_on(struct cyttsp *ts)
{
int error;
error = cyttsp_soft_reset(ts);
if (error)
return error;
error = cyttsp_load_bl_regs(ts);
if (error)
return error;
if (GET_BOOTLOADERMODE(ts->bl_data.bl_status) &&
IS_VALID_APP(ts->bl_data.bl_status)) {
error = cyttsp_exit_bl_mode(ts);
if (error)
return error;
}
if (GET_HSTMODE(ts->bl_data.bl_file) != CY_OPERATE_MODE ||
IS_OPERATIONAL_ERR(ts->bl_data.bl_status)) {
return -ENODEV;
}
error = cyttsp_set_sysinfo_mode(ts);
if (error)
return error;
error = cyttsp_set_sysinfo_regs(ts);
if (error)
return error;
error = cyttsp_set_operational_mode(ts);
if (error)
return error;
/* init active distance */
error = cyttsp_act_dist_setup(ts);
if (error)
return error;
ts->state = CY_ACTIVE_STATE;
return 0;
}
static int cyttsp_enable(struct cyttsp *ts)
{
int error;
/*
* The device firmware can wake on an I2C or SPI memory slave
* address match. So just reading a register is sufficient to
* wake up the device. The first read attempt will fail but it
* will wake it up making the second read attempt successful.
*/
error = ttsp_read_block_data(ts, CY_REG_BASE,
sizeof(ts->xy_data), &ts->xy_data);
if (error)
return error;
if (GET_HSTMODE(ts->xy_data.hst_mode))
return -EIO;
enable_irq(ts->irq);
return 0;
}
static int cyttsp_disable(struct cyttsp *ts)
{
int error;
error = ttsp_send_command(ts, CY_LOW_POWER_MODE);
if (error)
return error;
disable_irq(ts->irq);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int cyttsp_suspend(struct device *dev)
{
struct cyttsp *ts = dev_get_drvdata(dev);
int retval = 0;
mutex_lock(&ts->input->mutex);
if (ts->input->users) {
retval = cyttsp_disable(ts);
if (retval == 0)
ts->suspended = true;
}
mutex_unlock(&ts->input->mutex);
return retval;
}
static int cyttsp_resume(struct device *dev)
{
struct cyttsp *ts = dev_get_drvdata(dev);
mutex_lock(&ts->input->mutex);
if (ts->input->users)
cyttsp_enable(ts);
ts->suspended = false;
mutex_unlock(&ts->input->mutex);
return 0;
}
#endif
SIMPLE_DEV_PM_OPS(cyttsp_pm_ops, cyttsp_suspend, cyttsp_resume);
EXPORT_SYMBOL_GPL(cyttsp_pm_ops);
static int cyttsp_open(struct input_dev *dev)
{
struct cyttsp *ts = input_get_drvdata(dev);
int retval = 0;
if (!ts->suspended)
retval = cyttsp_enable(ts);
return retval;
}
static void cyttsp_close(struct input_dev *dev)
{
struct cyttsp *ts = input_get_drvdata(dev);
if (!ts->suspended)
cyttsp_disable(ts);
}
struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
struct device *dev, int irq, size_t xfer_buf_size)
{
const struct cyttsp_platform_data *pdata = dev->platform_data;
struct cyttsp *ts;
struct input_dev *input_dev;
int error;
if (!pdata || !pdata->name || irq <= 0) {
error = -EINVAL;
goto err_out;
}
ts = kzalloc(sizeof(*ts) + xfer_buf_size, GFP_KERNEL);
input_dev = input_allocate_device();
if (!ts || !input_dev) {
error = -ENOMEM;
goto err_free_mem;
}
ts->dev = dev;
ts->input = input_dev;
ts->pdata = dev->platform_data;
ts->bus_ops = bus_ops;
ts->irq = irq;
init_completion(&ts->bl_ready);
snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
if (pdata->init) {
error = pdata->init();
if (error) {
dev_err(ts->dev, "platform init failed, err: %d\n",
error);
goto err_free_mem;
}
}
input_dev->name = pdata->name;
input_dev->phys = ts->phys;
input_dev->id.bustype = bus_ops->bustype;
input_dev->dev.parent = ts->dev;
input_dev->open = cyttsp_open;
input_dev->close = cyttsp_close;
input_set_drvdata(input_dev, ts);
__set_bit(EV_ABS, input_dev->evbit);
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
0, pdata->maxx, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
0, pdata->maxy, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
0, CY_MAXZ, 0, 0);
input_mt_init_slots(input_dev, CY_MAX_ID);
error = request_threaded_irq(ts->irq, NULL, cyttsp_irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
pdata->name, ts);
if (error) {
dev_err(ts->dev, "failed to request IRQ %d, err: %d\n",
ts->irq, error);
goto err_platform_exit;
}
disable_irq(ts->irq);
error = cyttsp_power_on(ts);
if (error)
goto err_free_irq;
error = input_register_device(input_dev);
if (error) {
dev_err(ts->dev, "failed to register input device: %d\n",
error);
goto err_free_irq;
}
return ts;
err_free_irq:
free_irq(ts->irq, ts);
err_platform_exit:
if (pdata->exit)
pdata->exit();
err_free_mem:
input_free_device(input_dev);
kfree(ts);
err_out:
return ERR_PTR(error);
}
EXPORT_SYMBOL_GPL(cyttsp_probe);
void cyttsp_remove(struct cyttsp *ts)
{
free_irq(ts->irq, ts);
input_unregister_device(ts->input);
if (ts->pdata->exit)
ts->pdata->exit();
kfree(ts);
}
EXPORT_SYMBOL_GPL(cyttsp_remove);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen driver core");
MODULE_AUTHOR("Cypress");

View file

@ -0,0 +1,149 @@
/*
* 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__ */

View file

@ -0,0 +1,136 @@
/*
* 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");

View file

@ -0,0 +1,200 @@
/*
* 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");

View file

@ -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);

View file

@ -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");

View file

@ -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;

View file

@ -0,0 +1,360 @@
#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");

View file

@ -255,18 +255,7 @@ static struct i2c_driver max11801_ts_driver = {
.remove = __devexit_p(max11801_ts_remove),
};
static int __init max11801_ts_init(void)
{
return i2c_add_driver(&max11801_ts_driver);
}
static void __exit max11801_ts_exit(void)
{
i2c_del_driver(&max11801_ts_driver);
}
module_init(max11801_ts_init);
module_exit(max11801_ts_exit);
module_i2c_driver(max11801_ts_driver);
MODULE_AUTHOR("Zhang Jiejing <jiejing.zhang@freescale.com>");
MODULE_DESCRIPTION("Touchscreen driver for MAXI MAX11801 controller");

View file

@ -302,18 +302,7 @@ static struct i2c_driver mcs5000_ts_driver = {
.id_table = mcs5000_ts_id,
};
static int __init mcs5000_ts_init(void)
{
return i2c_add_driver(&mcs5000_ts_driver);
}
static void __exit mcs5000_ts_exit(void)
{
i2c_del_driver(&mcs5000_ts_driver);
}
module_init(mcs5000_ts_init);
module_exit(mcs5000_ts_exit);
module_i2c_driver(mcs5000_ts_driver);
/* Module information */
MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");

View file

@ -242,19 +242,8 @@ static struct i2c_driver migor_ts_driver = {
.id_table = migor_ts_id,
};
static int __init migor_ts_init(void)
{
return i2c_add_driver(&migor_ts_driver);
}
static void __exit migor_ts_exit(void)
{
i2c_del_driver(&migor_ts_driver);
}
module_i2c_driver(migor_ts_driver);
MODULE_DESCRIPTION("MigoR Touchscreen driver");
MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
MODULE_LICENSE("GPL");
module_init(migor_ts_init);
module_exit(migor_ts_exit);

View file

@ -222,17 +222,7 @@ static struct i2c_driver pixcir_i2c_ts_driver = {
.id_table = pixcir_i2c_ts_id,
};
static int __init pixcir_i2c_ts_init(void)
{
return i2c_add_driver(&pixcir_i2c_ts_driver);
}
module_init(pixcir_i2c_ts_init);
static void __exit pixcir_i2c_ts_exit(void)
{
i2c_del_driver(&pixcir_i2c_ts_driver);
}
module_exit(pixcir_i2c_ts_exit);
module_i2c_driver(pixcir_i2c_ts_driver);
MODULE_AUTHOR("Jianchun Bian <jcbian@pixcir.com.cn>, Dequan Meng <dqmeng@pixcir.com.cn>");
MODULE_DESCRIPTION("Pixcir I2C Touchscreen Driver");

View file

@ -268,17 +268,7 @@ static struct i2c_driver st1232_ts_driver = {
},
};
static int __init st1232_ts_init(void)
{
return i2c_add_driver(&st1232_ts_driver);
}
module_init(st1232_ts_init);
static void __exit st1232_ts_exit(void)
{
i2c_del_driver(&st1232_ts_driver);
}
module_exit(st1232_ts_exit);
module_i2c_driver(st1232_ts_driver);
MODULE_AUTHOR("Tony SIM <chinyeow.sim.xt@renesas.com>");
MODULE_DESCRIPTION("SITRONIX ST1232 Touchscreen Controller Driver");

View file

@ -0,0 +1,486 @@
/*
* TI Touch Screen driver
*
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.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 version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/input/ti_tscadc.h>
#include <linux/delay.h>
#define REG_IRQEOI 0x020
#define REG_RAWIRQSTATUS 0x024
#define REG_IRQSTATUS 0x028
#define REG_IRQENABLE 0x02C
#define REG_IRQWAKEUP 0x034
#define REG_CTRL 0x040
#define REG_ADCFSM 0x044
#define REG_CLKDIV 0x04C
#define REG_SE 0x054
#define REG_IDLECONFIG 0x058
#define REG_CHARGECONFIG 0x05C
#define REG_CHARGEDELAY 0x060
#define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8))
#define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8))
#define REG_STEPCONFIG13 0x0C4
#define REG_STEPDELAY13 0x0C8
#define REG_STEPCONFIG14 0x0CC
#define REG_STEPDELAY14 0x0D0
#define REG_FIFO0CNT 0xE4
#define REG_FIFO1THR 0xF4
#define REG_FIFO0 0x100
#define REG_FIFO1 0x200
/* Register Bitfields */
#define IRQWKUP_ENB BIT(0)
#define STPENB_STEPENB 0x7FFF
#define IRQENB_FIFO1THRES BIT(5)
#define IRQENB_PENUP BIT(9)
#define STEPCONFIG_MODE_HWSYNC 0x2
#define STEPCONFIG_SAMPLES_AVG (1 << 4)
#define STEPCONFIG_XPP (1 << 5)
#define STEPCONFIG_XNN (1 << 6)
#define STEPCONFIG_YPP (1 << 7)
#define STEPCONFIG_YNN (1 << 8)
#define STEPCONFIG_XNP (1 << 9)
#define STEPCONFIG_YPN (1 << 10)
#define STEPCONFIG_INM (1 << 18)
#define STEPCONFIG_INP (1 << 20)
#define STEPCONFIG_INP_5 (1 << 21)
#define STEPCONFIG_FIFO1 (1 << 26)
#define STEPCONFIG_OPENDLY 0xff
#define STEPCONFIG_Z1 (3 << 19)
#define STEPIDLE_INP (1 << 22)
#define STEPCHARGE_RFP (1 << 12)
#define STEPCHARGE_INM (1 << 15)
#define STEPCHARGE_INP (1 << 19)
#define STEPCHARGE_RFM (1 << 23)
#define STEPCHARGE_DELAY 0x1
#define CNTRLREG_TSCSSENB (1 << 0)
#define CNTRLREG_STEPID (1 << 1)
#define CNTRLREG_STEPCONFIGWRT (1 << 2)
#define CNTRLREG_4WIRE (1 << 5)
#define CNTRLREG_5WIRE (1 << 6)
#define CNTRLREG_8WIRE (3 << 5)
#define CNTRLREG_TSCENB (1 << 7)
#define ADCFSM_STEPID 0x10
#define SEQ_SETTLE 275
#define ADC_CLK 3000000
#define MAX_12BIT ((1 << 12) - 1)
#define TSCADC_DELTA_X 15
#define TSCADC_DELTA_Y 15
struct tscadc {
struct input_dev *input;
struct clk *tsc_ick;
void __iomem *tsc_base;
unsigned int irq;
unsigned int wires;
unsigned int x_plate_resistance;
bool pen_down;
};
static unsigned int tscadc_readl(struct tscadc *ts, unsigned int reg)
{
return readl(ts->tsc_base + reg);
}
static void tscadc_writel(struct tscadc *tsc, unsigned int reg,
unsigned int val)
{
writel(val, tsc->tsc_base + reg);
}
static void tscadc_step_config(struct tscadc *ts_dev)
{
unsigned int config;
int i;
/* Configure the Step registers */
config = STEPCONFIG_MODE_HWSYNC |
STEPCONFIG_SAMPLES_AVG | STEPCONFIG_XPP;
switch (ts_dev->wires) {
case 4:
config |= STEPCONFIG_INP | STEPCONFIG_XNN;
break;
case 5:
config |= STEPCONFIG_YNN |
STEPCONFIG_INP_5 | STEPCONFIG_XNN |
STEPCONFIG_YPP;
break;
case 8:
config |= STEPCONFIG_INP | STEPCONFIG_XNN;
break;
}
for (i = 1; i < 7; i++) {
tscadc_writel(ts_dev, REG_STEPCONFIG(i), config);
tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
}
config = 0;
config = STEPCONFIG_MODE_HWSYNC |
STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YNN |
STEPCONFIG_INM | STEPCONFIG_FIFO1;
switch (ts_dev->wires) {
case 4:
config |= STEPCONFIG_YPP;
break;
case 5:
config |= STEPCONFIG_XPP | STEPCONFIG_INP_5 |
STEPCONFIG_XNP | STEPCONFIG_YPN;
break;
case 8:
config |= STEPCONFIG_YPP;
break;
}
for (i = 7; i < 13; i++) {
tscadc_writel(ts_dev, REG_STEPCONFIG(i), config);
tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
}
config = 0;
/* Charge step configuration */
config = STEPCONFIG_XPP | STEPCONFIG_YNN |
STEPCHARGE_RFP | STEPCHARGE_RFM |
STEPCHARGE_INM | STEPCHARGE_INP;
tscadc_writel(ts_dev, REG_CHARGECONFIG, config);
tscadc_writel(ts_dev, REG_CHARGEDELAY, STEPCHARGE_DELAY);
config = 0;
/* Configure to calculate pressure */
config = STEPCONFIG_MODE_HWSYNC |
STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YPP |
STEPCONFIG_XNN | STEPCONFIG_INM;
tscadc_writel(ts_dev, REG_STEPCONFIG13, config);
tscadc_writel(ts_dev, REG_STEPDELAY13, STEPCONFIG_OPENDLY);
config |= STEPCONFIG_Z1 | STEPCONFIG_FIFO1;
tscadc_writel(ts_dev, REG_STEPCONFIG14, config);
tscadc_writel(ts_dev, REG_STEPDELAY14, STEPCONFIG_OPENDLY);
tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB);
}
static void tscadc_idle_config(struct tscadc *ts_config)
{
unsigned int idleconfig;
idleconfig = STEPCONFIG_YNN |
STEPCONFIG_INM |
STEPCONFIG_YPN | STEPIDLE_INP;
tscadc_writel(ts_config, REG_IDLECONFIG, idleconfig);
}
static void tscadc_read_coordinates(struct tscadc *ts_dev,
unsigned int *x, unsigned int *y)
{
unsigned int fifocount = tscadc_readl(ts_dev, REG_FIFO0CNT);
unsigned int prev_val_x = ~0, prev_val_y = ~0;
unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
unsigned int read, diff;
unsigned int i;
/*
* Delta filter is used to remove large variations in sampled
* values from ADC. The filter tries to predict where the next
* coordinate could be. This is done by taking a previous
* coordinate and subtracting it form current one. Further the
* algorithm compares the difference with that of a present value,
* if true the value is reported to the sub system.
*/
for (i = 0; i < fifocount - 1; i++) {
read = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff;
diff = abs(read - prev_val_x);
if (diff < prev_diff_x) {
prev_diff_x = diff;
*x = read;
}
prev_val_x = read;
read = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff;
diff = abs(read - prev_val_y);
if (diff < prev_diff_y) {
prev_diff_y = diff;
*y = read;
}
prev_val_y = read;
}
}
static irqreturn_t tscadc_irq(int irq, void *dev)
{
struct tscadc *ts_dev = dev;
struct input_dev *input_dev = ts_dev->input;
unsigned int status, irqclr = 0;
unsigned int x = 0, y = 0;
unsigned int z1, z2, z;
unsigned int fsm;
status = tscadc_readl(ts_dev, REG_IRQSTATUS);
if (status & IRQENB_FIFO1THRES) {
tscadc_read_coordinates(ts_dev, &x, &y);
z1 = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff;
z2 = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff;
if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
/*
* Calculate pressure using formula
* Resistance(touch) = x plate resistance *
* x postion/4096 * ((z2 / z1) - 1)
*/
z = z2 - z1;
z *= x;
z *= ts_dev->x_plate_resistance;
z /= z1;
z = (z + 2047) >> 12;
if (z <= MAX_12BIT) {
input_report_abs(input_dev, ABS_X, x);
input_report_abs(input_dev, ABS_Y, y);
input_report_abs(input_dev, ABS_PRESSURE, z);
input_report_key(input_dev, BTN_TOUCH, 1);
input_sync(input_dev);
}
}
irqclr |= IRQENB_FIFO1THRES;
}
/*
* Time for sequencer to settle, to read
* correct state of the sequencer.
*/
udelay(SEQ_SETTLE);
status = tscadc_readl(ts_dev, REG_RAWIRQSTATUS);
if (status & IRQENB_PENUP) {
/* Pen up event */
fsm = tscadc_readl(ts_dev, REG_ADCFSM);
if (fsm == ADCFSM_STEPID) {
ts_dev->pen_down = false;
input_report_key(input_dev, BTN_TOUCH, 0);
input_report_abs(input_dev, ABS_PRESSURE, 0);
input_sync(input_dev);
} else {
ts_dev->pen_down = true;
}
irqclr |= IRQENB_PENUP;
}
tscadc_writel(ts_dev, REG_IRQSTATUS, irqclr);
/* check pending interrupts */
tscadc_writel(ts_dev, REG_IRQEOI, 0x0);
tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB);
return IRQ_HANDLED;
}
/*
* The functions for inserting/removing driver as a module.
*/
static int __devinit tscadc_probe(struct platform_device *pdev)
{
const struct tsc_data *pdata = pdev->dev.platform_data;
struct resource *res;
struct tscadc *ts_dev;
struct input_dev *input_dev;
struct clk *clk;
int err;
int clk_value, ctrl, irq;
if (!pdata) {
dev_err(&pdev->dev, "missing platform data.\n");
return -EINVAL;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "no memory resource defined.\n");
return -EINVAL;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "no irq ID is specified.\n");
return -EINVAL;
}
/* Allocate memory for device */
ts_dev = kzalloc(sizeof(struct tscadc), GFP_KERNEL);
input_dev = input_allocate_device();
if (!ts_dev || !input_dev) {
dev_err(&pdev->dev, "failed to allocate memory.\n");
err = -ENOMEM;
goto err_free_mem;
}
ts_dev->input = input_dev;
ts_dev->irq = irq;
ts_dev->wires = pdata->wires;
ts_dev->x_plate_resistance = pdata->x_plate_resistance;
res = request_mem_region(res->start, resource_size(res), pdev->name);
if (!res) {
dev_err(&pdev->dev, "failed to reserve registers.\n");
err = -EBUSY;
goto err_free_mem;
}
ts_dev->tsc_base = ioremap(res->start, resource_size(res));
if (!ts_dev->tsc_base) {
dev_err(&pdev->dev, "failed to map registers.\n");
err = -ENOMEM;
goto err_release_mem_region;
}
err = request_irq(ts_dev->irq, tscadc_irq,
0, pdev->dev.driver->name, ts_dev);
if (err) {
dev_err(&pdev->dev, "failed to allocate irq.\n");
goto err_unmap_regs;
}
ts_dev->tsc_ick = clk_get(&pdev->dev, "adc_tsc_ick");
if (IS_ERR(ts_dev->tsc_ick)) {
dev_err(&pdev->dev, "failed to get TSC ick\n");
goto err_free_irq;
}
clk_enable(ts_dev->tsc_ick);
clk = clk_get(&pdev->dev, "adc_tsc_fck");
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get TSC fck\n");
err = PTR_ERR(clk);
goto err_disable_clk;
}
clk_value = clk_get_rate(clk) / ADC_CLK;
clk_put(clk);
if (clk_value < 7) {
dev_err(&pdev->dev, "clock input less than min clock requirement\n");
goto err_disable_clk;
}
/* CLKDIV needs to be configured to the value minus 1 */
tscadc_writel(ts_dev, REG_CLKDIV, clk_value - 1);
/* Enable wake-up of the SoC using touchscreen */
tscadc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
ctrl = CNTRLREG_STEPCONFIGWRT |
CNTRLREG_TSCENB |
CNTRLREG_STEPID;
switch (ts_dev->wires) {
case 4:
ctrl |= CNTRLREG_4WIRE;
break;
case 5:
ctrl |= CNTRLREG_5WIRE;
break;
case 8:
ctrl |= CNTRLREG_8WIRE;
break;
}
tscadc_writel(ts_dev, REG_CTRL, ctrl);
tscadc_idle_config(ts_dev);
tscadc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
tscadc_step_config(ts_dev);
tscadc_writel(ts_dev, REG_FIFO1THR, 6);
ctrl |= CNTRLREG_TSCSSENB;
tscadc_writel(ts_dev, REG_CTRL, ctrl);
input_dev->name = "ti-tsc-adc";
input_dev->dev.parent = &pdev->dev;
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
/* register to the input system */
err = input_register_device(input_dev);
if (err)
goto err_disable_clk;
platform_set_drvdata(pdev, ts_dev);
return 0;
err_disable_clk:
clk_disable(ts_dev->tsc_ick);
clk_put(ts_dev->tsc_ick);
err_free_irq:
free_irq(ts_dev->irq, ts_dev);
err_unmap_regs:
iounmap(ts_dev->tsc_base);
err_release_mem_region:
release_mem_region(res->start, resource_size(res));
err_free_mem:
input_free_device(input_dev);
kfree(ts_dev);
return err;
}
static int __devexit tscadc_remove(struct platform_device *pdev)
{
struct tscadc *ts_dev = platform_get_drvdata(pdev);
struct resource *res;
free_irq(ts_dev->irq, ts_dev);
input_unregister_device(ts_dev->input);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
iounmap(ts_dev->tsc_base);
release_mem_region(res->start, resource_size(res));
clk_disable(ts_dev->tsc_ick);
clk_put(ts_dev->tsc_ick);
kfree(ts_dev);
platform_set_drvdata(pdev, NULL);
return 0;
}
static struct platform_driver ti_tsc_driver = {
.probe = tscadc_probe,
.remove = __devexit_p(tscadc_remove),
.driver = {
.name = "tsc",
.owner = THIS_MODULE,
},
};
module_platform_driver(ti_tsc_driver);
MODULE_DESCRIPTION("TI touchscreen controller driver");
MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
MODULE_LICENSE("GPL");

View file

@ -747,17 +747,7 @@ static struct spi_driver tsc2005_driver = {
.remove = __devexit_p(tsc2005_remove),
};
static int __init tsc2005_init(void)
{
return spi_register_driver(&tsc2005_driver);
}
module_init(tsc2005_init);
static void __exit tsc2005_exit(void)
{
spi_unregister_driver(&tsc2005_driver);
}
module_exit(tsc2005_exit);
module_spi_driver(tsc2005_driver);
MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>");
MODULE_DESCRIPTION("TSC2005 Touchscreen Driver");

View file

@ -399,18 +399,7 @@ static struct i2c_driver tsc2007_driver = {
.remove = __devexit_p(tsc2007_remove),
};
static int __init tsc2007_init(void)
{
return i2c_add_driver(&tsc2007_driver);
}
static void __exit tsc2007_exit(void)
{
i2c_del_driver(&tsc2007_driver);
}
module_init(tsc2007_init);
module_exit(tsc2007_exit);
module_i2c_driver(tsc2007_driver);
MODULE_AUTHOR("Kwangwoo Lee <kwlee@mtekvision.com>");
MODULE_DESCRIPTION("TSC2007 TouchScreen Driver");

View file

@ -17,6 +17,7 @@
* - Zytronic capacitive touchscreen
* - NEXIO/iNexio
* - Elo TouchSystems 2700 IntelliTouch
* - EasyTouch USB Dual/Multi touch controller from Data Modul
*
* Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch>
* Copyright (C) by Todd E. Johnson (mtouchusb.c)
@ -140,6 +141,7 @@ enum {
DEVTYPE_TC45USB,
DEVTYPE_NEXIO,
DEVTYPE_ELO,
DEVTYPE_ETOUCH,
};
#define USB_DEVICE_HID_CLASS(vend, prod) \
@ -245,6 +247,10 @@ static const struct usb_device_id usbtouch_devices[] = {
{USB_DEVICE(0x04e7, 0x0020), .driver_info = DEVTYPE_ELO},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH
{USB_DEVICE(0x7374, 0x0001), .driver_info = DEVTYPE_ETOUCH},
#endif
{}
};
@ -326,6 +332,51 @@ static int egalax_get_pkt_len(unsigned char *buf, int len)
}
#endif
/*****************************************************************************
* EasyTouch part
*/
#ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH
#ifndef MULTI_PACKET
#define MULTI_PACKET
#endif
#define ETOUCH_PKT_TYPE_MASK 0xFE
#define ETOUCH_PKT_TYPE_REPT 0x80
#define ETOUCH_PKT_TYPE_REPT2 0xB0
#define ETOUCH_PKT_TYPE_DIAG 0x0A
static int etouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
if ((pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT &&
(pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT2)
return 0;
dev->x = ((pkt[1] & 0x1F) << 7) | (pkt[2] & 0x7F);
dev->y = ((pkt[3] & 0x1F) << 7) | (pkt[4] & 0x7F);
dev->touch = pkt[0] & 0x01;
return 1;
}
static int etouch_get_pkt_len(unsigned char *buf, int len)
{
switch (buf[0] & ETOUCH_PKT_TYPE_MASK) {
case ETOUCH_PKT_TYPE_REPT:
case ETOUCH_PKT_TYPE_REPT2:
return 5;
case ETOUCH_PKT_TYPE_DIAG:
if (len < 2)
return -1;
return buf[1] + 2;
}
return 0;
}
#endif
/*****************************************************************************
* PanJit Part
@ -1175,6 +1226,18 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
.exit = nexio_exit,
},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH
[DEVTYPE_ETOUCH] = {
.min_xc = 0x0,
.max_xc = 0x07ff,
.min_yc = 0x0,
.max_yc = 0x07ff,
.rept_size = 16,
.process_pkt = usbtouch_process_multi,
.get_pkt_len = etouch_get_pkt_len,
.read_data = etouch_read_data,
},
#endif
};

View file

@ -114,6 +114,31 @@ struct input_keymap_entry {
#define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) /* get unique identifier */
#define EVIOCGPROP(len) _IOC(_IOC_READ, 'E', 0x09, len) /* get device properties */
/**
* EVIOCGMTSLOTS(len) - get MT slot values
*
* The ioctl buffer argument should be binary equivalent to
*
* struct input_mt_request_layout {
* __u32 code;
* __s32 values[num_slots];
* };
*
* where num_slots is the (arbitrary) number of MT slots to extract.
*
* The ioctl size argument (len) is the size of the buffer, which
* should satisfy len = (num_slots + 1) * sizeof(__s32). If len is
* too small to fit all available slots, the first num_slots are
* returned.
*
* Before the call, code is set to the wanted ABS_MT event type. On
* return, values[] is filled with the slot values for the specified
* ABS_MT code.
*
* If the request code is not an ABS_MT value, -EINVAL is returned.
*/
#define EVIOCGMTSLOTS(len) _IOC(_IOC_READ, 'E', 0x0a, len)
#define EVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len) /* get global key state */
#define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len) /* get all LEDs */
#define EVIOCGSND(len) _IOC(_IOC_READ, 'E', 0x1a, len) /* get all sounds status */
@ -129,6 +154,8 @@ struct input_keymap_entry {
#define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */
#define EVIOCSCLOCKID _IOW('E', 0xa0, int) /* Set clockid to be used for timestamps */
/*
* Device properties and quirks
*/

View file

@ -0,0 +1,58 @@
/*
* 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_H_
#define _CYTTSP_H_
#define CY_SPI_NAME "cyttsp-spi"
#define CY_I2C_NAME "cyttsp-i2c"
/* Active Power state scanning/processing refresh interval */
#define CY_ACT_INTRVL_DFLT 0x00 /* ms */
/* touch timeout for the Active power */
#define CY_TCH_TMOUT_DFLT 0xFF /* ms */
/* Low Power state scanning/processing refresh interval */
#define CY_LP_INTRVL_DFLT 0x0A /* ms */
/* Active distance in pixels for a gesture to be reported */
#define CY_ACT_DIST_DFLT 0xF8 /* pixels */
struct cyttsp_platform_data {
u32 maxx;
u32 maxy;
bool use_hndshk;
u8 act_dist; /* Active distance */
u8 act_intrvl; /* Active refresh interval; ms */
u8 tch_tmout; /* Active touch timeout; ms */
u8 lp_intrvl; /* Low power refresh interval; ms */
int (*init)(void);
void (*exit)(void);
char *name;
s16 irq_gpio;
u8 *bl_keys;
};
#endif /* _CYTTSP_H_ */

View file

@ -0,0 +1,10 @@
#ifndef _ILI210X_H
#define _ILI210X_H
struct ili210x_platform_data {
unsigned long irq_flags;
unsigned int poll_period;
bool (*get_pendown_state)(void);
};
#endif

View file

@ -24,6 +24,7 @@
struct kxtj9_platform_data {
unsigned int min_interval; /* minimum poll interval (in milli-seconds) */
unsigned int init_interval; /* initial poll interval (in milli-seconds) */
/*
* By default, x is axis 0, y is axis 1, z is axis 2; these can be
@ -52,16 +53,6 @@ struct kxtj9_platform_data {
#define KXTJ9_G_8G (1 << 4)
u8 g_range;
/* DATA_CTRL_REG: controls the output data rate of the part */
#define ODR12_5F 0
#define ODR25F 1
#define ODR50F 2
#define ODR100F 3
#define ODR200F 4
#define ODR400F 5
#define ODR800F 6
u8 data_odr_init;
int (*init)(void);
void (*exit)(void);
int (*power_on)(void);

View file

@ -3,6 +3,7 @@
#include <linux/types.h>
#include <linux/input.h>
#include <linux/of.h>
#define MATRIX_MAX_ROWS 32
#define MATRIX_MAX_COLS 32
@ -106,4 +107,22 @@ matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
__clear_bit(KEY_RESERVED, keybit);
}
#ifdef CONFIG_INPUT_OF_MATRIX_KEYMAP
struct matrix_keymap_data *
matrix_keyboard_of_fill_keymap(struct device_node *np, const char *propname);
void matrix_keyboard_of_free_keymap(const struct matrix_keymap_data *kd);
#else
static inline struct matrix_keymap_data *
matrix_keyboard_of_fill_keymap(struct device_node *np, const char *propname)
{
return NULL;
}
static inline void
matrix_keyboard_of_free_keymap(const struct matrix_keymap_data *kd)
{
}
#endif
#endif /* _MATRIX_KEYPAD_H */

View file

@ -48,10 +48,14 @@ static inline void input_mt_slot(struct input_dev *dev, int slot)
input_event(dev, EV_ABS, ABS_MT_SLOT, slot);
}
static inline bool input_is_mt_value(int axis)
{
return axis >= ABS_MT_FIRST && axis <= ABS_MT_LAST;
}
static inline bool input_is_mt_axis(int axis)
{
return axis == ABS_MT_SLOT ||
(axis >= ABS_MT_FIRST && axis <= ABS_MT_LAST);
return axis == ABS_MT_SLOT || input_is_mt_value(axis);
}
void input_mt_report_slot_state(struct input_dev *dev,

View file

@ -0,0 +1,17 @@
#ifndef __LINUX_TI_TSCADC_H
#define __LINUX_TI_TSCADC_H
/**
* struct tsc_data Touchscreen wire configuration
* @wires: Wires refer to application modes
* i.e. 4/5/8 wire touchscreen support
* on the platform.
* @x_plate_resistance: X plate resistance.
*/
struct tsc_data {
int wires;
int x_plate_resistance;
};
#endif

View file

@ -131,6 +131,55 @@ struct max8997_muic_platform_data {
int num_init_data;
};
enum max8997_haptic_motor_type {
MAX8997_HAPTIC_ERM,
MAX8997_HAPTIC_LRA,
};
enum max8997_haptic_pulse_mode {
MAX8997_EXTERNAL_MODE,
MAX8997_INTERNAL_MODE,
};
enum max8997_haptic_pwm_divisor {
MAX8997_PWM_DIVISOR_32,
MAX8997_PWM_DIVISOR_64,
MAX8997_PWM_DIVISOR_128,
MAX8997_PWM_DIVISOR_256,
};
/**
* max8997_haptic_platform_data
* @pwm_channel_id: channel number of PWM device
* valid for MAX8997_EXTERNAL_MODE
* @pwm_period: period in nano second for PWM device
* valid for MAX8997_EXTERNAL_MODE
* @type: motor type
* @mode: pulse mode
* MAX8997_EXTERNAL_MODE: external PWM device is used to control motor
* MAX8997_INTERNAL_MODE: internal pulse generator is used to control motor
* @pwm_divisor: divisor for external PWM device
* @internal_mode_pattern: internal mode pattern for internal mode
* [0 - 3]: valid pattern number
* @pattern_cycle: the number of cycles of the waveform
* for the internal mode pattern
* [0 - 15]: available cycles
* @pattern_signal_period: period of the waveform for the internal mode pattern
* [0 - 255]: available period
*/
struct max8997_haptic_platform_data {
unsigned int pwm_channel_id;
unsigned int pwm_period;
enum max8997_haptic_motor_type type;
enum max8997_haptic_pulse_mode mode;
enum max8997_haptic_pwm_divisor pwm_divisor;
unsigned int internal_mode_pattern;
unsigned int pattern_cycle;
unsigned int pattern_signal_period;
};
enum max8997_led_mode {
MAX8997_NONE,
MAX8997_FLASH_MODE,
@ -192,7 +241,9 @@ struct max8997_platform_data {
/* ---- MUIC ---- */
struct max8997_muic_platform_data *muic_pdata;
/* HAPTIC: Not implemented */
/* ---- HAPTIC ---- */
struct max8997_haptic_platform_data *haptic_pdata;
/* RTC: Not implemented */
/* ---- LED ---- */
struct max8997_led_platform_data *led_pdata;

View file

@ -0,0 +1,13 @@
#ifndef __LINUX_INPUT_OMAP4_KEYPAD_H
#define __LINUX_INPUT_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;
};
#endif /* __LINUX_INPUT_OMAP4_KEYPAD_H */

Some files were not shown because too many files have changed in this diff Show more