1
0
Fork 0

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

Pull input subsystem updates from Dmitry Torokhov:
 "Two new drivers for Elan hardware (for I2C touchpad and touchscreen
  found in several Chromebooks and other devices), a driver for Goodix
  touch panel, and small fixes to Cypress I2C trackpad and other input
  drivers.

  Also we switched to use __maybe_unused instead of gating suspend/
  resume code with #ifdef guards to get better compile coverage"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (27 commits)
  Input: gpio_keys - fix warning regarding uninitialized 'button' variable
  Input: add support for Elan eKTH I2C touchscreens
  Input: gpio_keys - fix warning regarding uninitialized  'irq' variable
  Input: cyapa - use 'error' for error codes
  Input: cyapa - fix resuming the device
  Input: gpio_keys - add device tree support for interrupt only keys
  Input: amikbd - allocate temporary keymap buffer on the stack
  Input: amikbd - fix build if !CONFIG_HW_CONSOLE
  Input: lm8323 - missing error check in lm8323_set_disable()
  Input: initialize device counter variables with -1
  Input: initialize input_no to -1 to avoid subtraction
  Input: i8042 - do not try to load on Intel NUC D54250WYK
  Input: atkbd - correct MSC_SCAN events for force_release keys
  Input: cyapa - switch to using managed resources
  Input: lifebook - use "static inline" instead of "inline" in lifebook.h
  Input: touchscreen - use __maybe_unused instead of ifdef around suspend/resume
  Input: mouse - use __maybe_unused instead of ifdef around suspend/resume
  Input: misc - use __maybe_unused instead of ifdef around suspend/resume
  Input: cap11xx - support for irq-active-high option
  Input: cap11xx - add support for various cap11xx devices
  ...
wifi-calibration
Linus Torvalds 2014-12-17 10:06:02 -08:00
commit d797da41b2
77 changed files with 4950 additions and 923 deletions

View File

@ -1,14 +1,16 @@
Device tree bindings for Microchip CAP1106, 6 channel capacitive touch sensor
Device tree bindings for Microchip CAP11xx based capacitive touch sensors
The node for this driver must be a child of a I2C controller node, as the
The node for this device must be a child of a I2C controller node, as the
device communication via I2C only.
Required properties:
compatible: Must be "microchip,cap1106"
compatible: Must contain one of:
"microchip,cap1106"
"microchip,cap1126"
"microchip,cap1188"
reg: The I2C slave address of the device.
Only 0x28 is valid.
interrupts: Property describing the interrupt line the
device's ALERT#/CM_IRQ# pin is connected to.
@ -26,6 +28,10 @@ Optional properties:
Valid values are 1, 2, 4, and 8.
By default, a gain of 1 is set.
microchip,irq-active-high: By default the interrupt pin is active low
open drain. This property allows using the active
high push-pull output.
linux,keycodes: Specifies an array of numeric keycode values to
be used for the channels. If this property is
omitted, KEY_A, KEY_B, etc are used as
@ -43,11 +49,11 @@ i2c_controller {
autorepeat;
microchip,sensor-gain = <2>;
linux,keycodes = <103 /* KEY_UP */
106 /* KEY_RIGHT */
108 /* KEY_DOWN */
105 /* KEY_LEFT */
109 /* KEY_PAGEDOWN */
104>; /* KEY_PAGEUP */
linux,keycodes = <103>, /* KEY_UP */
<106>, /* KEY_RIGHT */
<108>, /* KEY_DOWN */
<105>, /* KEY_LEFT */
<109>, /* KEY_PAGEDOWN */
<104>; /* KEY_PAGEUP */
};
}

View File

@ -0,0 +1,34 @@
Elantech I2C Touchpad
Required properties:
- compatible: must be "elan,ekth3000".
- reg: I2C address of the chip.
- interrupt-parent: a phandle for the interrupt controller (see interrupt
binding[0]).
- interrupts: interrupt to which the chip is connected (see interrupt
binding[0]).
Optional properties:
- wakeup-source: touchpad can be used as a wakeup source.
- pinctrl-names: should be "default" (see pinctrl binding [1]).
- pinctrl-0: a phandle pointing to the pin settings for the device (see
pinctrl binding [1]).
- vcc-supply: a phandle for the regulator supplying 3.3V power.
[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
[1]: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
Example:
&i2c1 {
/* ... */
touchpad@15 {
compatible = "elan,ekth3000";
reg = <0x15>;
interrupt-parent = <&gpio4>;
interrupts = <0x0 IRQ_TYPE_EDGE_FALLING>;
wakeup-source;
};
/* ... */
};

View File

@ -0,0 +1,33 @@
Elantech I2C Touchscreen
Required properties:
- compatible: must be "elan,ekth3500".
- reg: I2C address of the chip.
- interrupt-parent: a phandle for the interrupt controller (see interrupt
binding[0]).
- interrupts: interrupt to which the chip is connected (see interrupt
binding[0]).
Optional properties:
- wakeup-source: touchscreen can be used as a wakeup source.
- pinctrl-names: should be "default" (see pinctrl binding [1]).
- pinctrl-0: a phandle pointing to the pin settings for the device (see
pinctrl binding [1]).
[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
[1]: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
Example:
&i2c1 {
/* ... */
touchscreen@10 {
compatible = "elan,ekth3500";
reg = <0x10>;
interrupt-parent = <&gpio4>;
interrupts = <0x0 IRQ_TYPE_EDGE_FALLING>;
wakeup-source;
};
/* ... */
};

View File

@ -10,10 +10,13 @@ Optional properties:
Each button (key) is represented as a sub-node of "gpio-keys":
Subnode properties:
- gpios: OF device-tree gpio specification.
- label: Descriptive name of the key.
- linux,code: Keycode to emit.
Required mutual exclusive subnode-properties:
- gpios: OF device-tree gpio specification.
- interrupts: the interrupt line for that input
Optional subnode-properties:
- linux,input-type: Specify event type this button/key generates.
If not specified defaults to <1> == EV_KEY.
@ -33,4 +36,9 @@ Example nodes:
linux,code = <103>;
gpios = <&gpio1 0 1>;
};
button@22 {
label = "GPIO Key DOWN";
linux,code = <108>;
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
};
...

View File

@ -47,6 +47,7 @@ dlink D-Link Corporation
dmo Data Modul AG
ebv EBV Elektronik
edt Emerging Display Technologies
elan Elan Microelectronic Corp.
emmicro EM Microelectronic
energymicro Silicon Laboratories (formerly Energy Micro AS)
epcos EPCOS AG

View File

@ -4255,6 +4255,12 @@ L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/usb/go7007/
GOODIX TOUCHSCREEN
M: Bastien Nocera <hadess@hadess.net>
L: linux-input@vger.kernel.org
S: Maintained
F: drivers/input/touchscreen/goodix.c
GPIO SUBSYSTEM
M: Linus Walleij <linus.walleij@linaro.org>
M: Alexandre Courbot <gnurou@gmail.com>

View File

@ -527,14 +527,14 @@ EXPORT_SYMBOL(gameport_set_phys);
*/
static void gameport_init_port(struct gameport *gameport)
{
static atomic_t gameport_no = ATOMIC_INIT(0);
static atomic_t gameport_no = ATOMIC_INIT(-1);
__module_get(THIS_MODULE);
mutex_init(&gameport->drv_mutex);
device_initialize(&gameport->dev);
dev_set_name(&gameport->dev, "gameport%lu",
(unsigned long)atomic_inc_return(&gameport_no) - 1);
(unsigned long)atomic_inc_return(&gameport_no));
gameport->dev.bus = &gameport_bus;
gameport->dev.release = gameport_release_port;
if (gameport->parent)

View File

@ -1775,7 +1775,7 @@ EXPORT_SYMBOL_GPL(input_class);
*/
struct input_dev *input_allocate_device(void)
{
static atomic_t input_no = ATOMIC_INIT(0);
static atomic_t input_no = ATOMIC_INIT(-1);
struct input_dev *dev;
dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
@ -1790,7 +1790,7 @@ struct input_dev *input_allocate_device(void)
INIT_LIST_HEAD(&dev->node);
dev_set_name(&dev->dev, "input%lu",
(unsigned long) atomic_inc_return(&input_no) - 1);
(unsigned long)atomic_inc_return(&input_no));
__module_get(THIS_MODULE);
}

View File

@ -886,8 +886,8 @@ static void xpad_led_set(struct led_classdev *led_cdev,
static int xpad_led_probe(struct usb_xpad *xpad)
{
static atomic_t led_seq = ATOMIC_INIT(0);
long led_no;
static atomic_t led_seq = ATOMIC_INIT(-1);
unsigned long led_no;
struct xpad_led *led;
struct led_classdev *led_cdev;
int error;
@ -899,9 +899,9 @@ static int xpad_led_probe(struct usb_xpad *xpad)
if (!led)
return -ENOMEM;
led_no = (long)atomic_inc_return(&led_seq) - 1;
led_no = atomic_inc_return(&led_seq);
snprintf(led->name, sizeof(led->name), "xpad%ld", led_no);
snprintf(led->name, sizeof(led->name), "xpad%lu", led_no);
led->xpad = xpad;
led_cdev = &led->led_cdev;

View File

@ -665,14 +665,14 @@ config KEYBOARD_CROS_EC
To compile this driver as a module, choose M here: the
module will be called cros_ec_keyb.
config KEYBOARD_CAP1106
tristate "Microchip CAP1106 touch sensor"
config KEYBOARD_CAP11XX
tristate "Microchip CAP11XX based touch sensors"
depends on OF && I2C
select REGMAP_I2C
help
Say Y here to enable the CAP1106 touch sensor driver.
Say Y here to enable the CAP11XX touch sensor driver.
To compile this driver as a module, choose M here: the
module will be called cap1106.
module will be called cap11xx.
endif

View File

@ -11,7 +11,7 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o
obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o
obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
obj-$(CONFIG_KEYBOARD_CAP1106) += cap1106.o
obj-$(CONFIG_KEYBOARD_CAP11XX) += cap11xx.o
obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o
obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o
obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o

View File

@ -45,6 +45,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Amiga keyboard driver");
MODULE_LICENSE("GPL");
#ifdef CONFIG_HW_CONSOLE
static unsigned char amikbd_keycode[0x78] __initdata = {
[0] = KEY_GRAVE,
[1] = KEY_1,
@ -144,6 +145,32 @@ static unsigned char amikbd_keycode[0x78] __initdata = {
[103] = KEY_RIGHTMETA
};
static void __init amikbd_init_console_keymaps(void)
{
/* We can spare 512 bytes on stack for temp_map in init path. */
unsigned short temp_map[NR_KEYS];
int i, j;
for (i = 0; i < MAX_NR_KEYMAPS; i++) {
if (!key_maps[i])
continue;
memset(temp_map, 0, sizeof(temp_map));
for (j = 0; j < 0x78; j++) {
if (!amikbd_keycode[j])
continue;
temp_map[j] = key_maps[i][amikbd_keycode[j]];
}
for (j = 0; j < NR_KEYS; j++) {
if (!temp_map[j])
temp_map[j] = 0xf200;
}
memcpy(key_maps[i], temp_map, sizeof(temp_map));
}
}
#else /* !CONFIG_HW_CONSOLE */
static inline void amikbd_init_console_keymaps(void) {}
#endif /* !CONFIG_HW_CONSOLE */
static const char *amikbd_messages[8] = {
[0] = KERN_ALERT "amikbd: Ctrl-Amiga-Amiga reset warning!!\n",
[1] = KERN_WARNING "amikbd: keyboard lost sync\n",
@ -186,7 +213,7 @@ static irqreturn_t amikbd_interrupt(int irq, void *data)
static int __init amikbd_probe(struct platform_device *pdev)
{
struct input_dev *dev;
int i, j, err;
int i, err;
dev = input_allocate_device();
if (!dev) {
@ -207,22 +234,8 @@ static int __init amikbd_probe(struct platform_device *pdev)
for (i = 0; i < 0x78; i++)
set_bit(i, dev->keybit);
for (i = 0; i < MAX_NR_KEYMAPS; i++) {
static u_short temp_map[NR_KEYS] __initdata;
if (!key_maps[i])
continue;
memset(temp_map, 0, sizeof(temp_map));
for (j = 0; j < 0x78; j++) {
if (!amikbd_keycode[j])
continue;
temp_map[j] = key_maps[i][amikbd_keycode[j]];
}
for (j = 0; j < NR_KEYS; j++) {
if (!temp_map[j])
temp_map[j] = 0xf200;
}
memcpy(key_maps[i], temp_map, sizeof(temp_map));
}
amikbd_init_console_keymaps();
ciaa.cra &= ~0x41; /* serial data in, turn off TA */
err = request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd",
dev);

View File

@ -456,8 +456,9 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
keycode = atkbd->keycode[code];
if (keycode != ATKBD_KEY_NULL)
input_event(dev, EV_MSC, MSC_SCAN, code);
if (!(atkbd->release && test_bit(code, atkbd->force_release_mask)))
if (keycode != ATKBD_KEY_NULL)
input_event(dev, EV_MSC, MSC_SCAN, code);
switch (keycode) {
case ATKBD_KEY_NULL:
@ -511,6 +512,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
input_sync(dev);
if (value && test_bit(code, atkbd->force_release_mask)) {
input_event(dev, EV_MSC, MSC_SCAN, code);
input_report_key(dev, keycode, 0);
input_sync(dev);
}

View File

@ -1,341 +0,0 @@
/*
* Input driver for Microchip CAP1106, 6 channel capacitive touch sensor
*
* http://www.microchip.com/wwwproducts/Devices.aspx?product=CAP1106
*
* (c) 2014 Daniel Mack <linux@zonque.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/of_irq.h>
#include <linux/regmap.h>
#include <linux/i2c.h>
#include <linux/gpio/consumer.h>
#define CAP1106_REG_MAIN_CONTROL 0x00
#define CAP1106_REG_MAIN_CONTROL_GAIN_SHIFT (6)
#define CAP1106_REG_MAIN_CONTROL_GAIN_MASK (0xc0)
#define CAP1106_REG_MAIN_CONTROL_DLSEEP BIT(4)
#define CAP1106_REG_GENERAL_STATUS 0x02
#define CAP1106_REG_SENSOR_INPUT 0x03
#define CAP1106_REG_NOISE_FLAG_STATUS 0x0a
#define CAP1106_REG_SENOR_DELTA(X) (0x10 + (X))
#define CAP1106_REG_SENSITIVITY_CONTROL 0x1f
#define CAP1106_REG_CONFIG 0x20
#define CAP1106_REG_SENSOR_ENABLE 0x21
#define CAP1106_REG_SENSOR_CONFIG 0x22
#define CAP1106_REG_SENSOR_CONFIG2 0x23
#define CAP1106_REG_SAMPLING_CONFIG 0x24
#define CAP1106_REG_CALIBRATION 0x26
#define CAP1106_REG_INT_ENABLE 0x27
#define CAP1106_REG_REPEAT_RATE 0x28
#define CAP1106_REG_MT_CONFIG 0x2a
#define CAP1106_REG_MT_PATTERN_CONFIG 0x2b
#define CAP1106_REG_MT_PATTERN 0x2d
#define CAP1106_REG_RECALIB_CONFIG 0x2f
#define CAP1106_REG_SENSOR_THRESH(X) (0x30 + (X))
#define CAP1106_REG_SENSOR_NOISE_THRESH 0x38
#define CAP1106_REG_STANDBY_CHANNEL 0x40
#define CAP1106_REG_STANDBY_CONFIG 0x41
#define CAP1106_REG_STANDBY_SENSITIVITY 0x42
#define CAP1106_REG_STANDBY_THRESH 0x43
#define CAP1106_REG_CONFIG2 0x44
#define CAP1106_REG_SENSOR_BASE_CNT(X) (0x50 + (X))
#define CAP1106_REG_SENSOR_CALIB (0xb1 + (X))
#define CAP1106_REG_SENSOR_CALIB_LSB1 0xb9
#define CAP1106_REG_SENSOR_CALIB_LSB2 0xba
#define CAP1106_REG_PRODUCT_ID 0xfd
#define CAP1106_REG_MANUFACTURER_ID 0xfe
#define CAP1106_REG_REVISION 0xff
#define CAP1106_NUM_CHN 6
#define CAP1106_PRODUCT_ID 0x55
#define CAP1106_MANUFACTURER_ID 0x5d
struct cap1106_priv {
struct regmap *regmap;
struct input_dev *idev;
/* config */
unsigned short keycodes[CAP1106_NUM_CHN];
};
static const struct reg_default cap1106_reg_defaults[] = {
{ CAP1106_REG_MAIN_CONTROL, 0x00 },
{ CAP1106_REG_GENERAL_STATUS, 0x00 },
{ CAP1106_REG_SENSOR_INPUT, 0x00 },
{ CAP1106_REG_NOISE_FLAG_STATUS, 0x00 },
{ CAP1106_REG_SENSITIVITY_CONTROL, 0x2f },
{ CAP1106_REG_CONFIG, 0x20 },
{ CAP1106_REG_SENSOR_ENABLE, 0x3f },
{ CAP1106_REG_SENSOR_CONFIG, 0xa4 },
{ CAP1106_REG_SENSOR_CONFIG2, 0x07 },
{ CAP1106_REG_SAMPLING_CONFIG, 0x39 },
{ CAP1106_REG_CALIBRATION, 0x00 },
{ CAP1106_REG_INT_ENABLE, 0x3f },
{ CAP1106_REG_REPEAT_RATE, 0x3f },
{ CAP1106_REG_MT_CONFIG, 0x80 },
{ CAP1106_REG_MT_PATTERN_CONFIG, 0x00 },
{ CAP1106_REG_MT_PATTERN, 0x3f },
{ CAP1106_REG_RECALIB_CONFIG, 0x8a },
{ CAP1106_REG_SENSOR_THRESH(0), 0x40 },
{ CAP1106_REG_SENSOR_THRESH(1), 0x40 },
{ CAP1106_REG_SENSOR_THRESH(2), 0x40 },
{ CAP1106_REG_SENSOR_THRESH(3), 0x40 },
{ CAP1106_REG_SENSOR_THRESH(4), 0x40 },
{ CAP1106_REG_SENSOR_THRESH(5), 0x40 },
{ CAP1106_REG_SENSOR_NOISE_THRESH, 0x01 },
{ CAP1106_REG_STANDBY_CHANNEL, 0x00 },
{ CAP1106_REG_STANDBY_CONFIG, 0x39 },
{ CAP1106_REG_STANDBY_SENSITIVITY, 0x02 },
{ CAP1106_REG_STANDBY_THRESH, 0x40 },
{ CAP1106_REG_CONFIG2, 0x40 },
{ CAP1106_REG_SENSOR_CALIB_LSB1, 0x00 },
{ CAP1106_REG_SENSOR_CALIB_LSB2, 0x00 },
};
static bool cap1106_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case CAP1106_REG_MAIN_CONTROL:
case CAP1106_REG_SENSOR_INPUT:
case CAP1106_REG_SENOR_DELTA(0):
case CAP1106_REG_SENOR_DELTA(1):
case CAP1106_REG_SENOR_DELTA(2):
case CAP1106_REG_SENOR_DELTA(3):
case CAP1106_REG_SENOR_DELTA(4):
case CAP1106_REG_SENOR_DELTA(5):
case CAP1106_REG_PRODUCT_ID:
case CAP1106_REG_MANUFACTURER_ID:
case CAP1106_REG_REVISION:
return true;
}
return false;
}
static const struct regmap_config cap1106_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = CAP1106_REG_REVISION,
.reg_defaults = cap1106_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(cap1106_reg_defaults),
.cache_type = REGCACHE_RBTREE,
.volatile_reg = cap1106_volatile_reg,
};
static irqreturn_t cap1106_thread_func(int irq_num, void *data)
{
struct cap1106_priv *priv = data;
unsigned int status;
int ret, i;
/*
* Deassert interrupt. This needs to be done before reading the status
* registers, which will not carry valid values otherwise.
*/
ret = regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL, 1, 0);
if (ret < 0)
goto out;
ret = regmap_read(priv->regmap, CAP1106_REG_SENSOR_INPUT, &status);
if (ret < 0)
goto out;
for (i = 0; i < CAP1106_NUM_CHN; i++)
input_report_key(priv->idev, priv->keycodes[i],
status & (1 << i));
input_sync(priv->idev);
out:
return IRQ_HANDLED;
}
static int cap1106_set_sleep(struct cap1106_priv *priv, bool sleep)
{
return regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL,
CAP1106_REG_MAIN_CONTROL_DLSEEP,
sleep ? CAP1106_REG_MAIN_CONTROL_DLSEEP : 0);
}
static int cap1106_input_open(struct input_dev *idev)
{
struct cap1106_priv *priv = input_get_drvdata(idev);
return cap1106_set_sleep(priv, false);
}
static void cap1106_input_close(struct input_dev *idev)
{
struct cap1106_priv *priv = input_get_drvdata(idev);
cap1106_set_sleep(priv, true);
}
static int cap1106_i2c_probe(struct i2c_client *i2c_client,
const struct i2c_device_id *id)
{
struct device *dev = &i2c_client->dev;
struct cap1106_priv *priv;
struct device_node *node;
int i, error, irq, gain = 0;
unsigned int val, rev;
u32 gain32, keycodes[CAP1106_NUM_CHN];
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->regmap = devm_regmap_init_i2c(i2c_client, &cap1106_regmap_config);
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);
error = regmap_read(priv->regmap, CAP1106_REG_PRODUCT_ID, &val);
if (error)
return error;
if (val != CAP1106_PRODUCT_ID) {
dev_err(dev, "Product ID: Got 0x%02x, expected 0x%02x\n",
val, CAP1106_PRODUCT_ID);
return -ENODEV;
}
error = regmap_read(priv->regmap, CAP1106_REG_MANUFACTURER_ID, &val);
if (error)
return error;
if (val != CAP1106_MANUFACTURER_ID) {
dev_err(dev, "Manufacturer ID: Got 0x%02x, expected 0x%02x\n",
val, CAP1106_MANUFACTURER_ID);
return -ENODEV;
}
error = regmap_read(priv->regmap, CAP1106_REG_REVISION, &rev);
if (error < 0)
return error;
dev_info(dev, "CAP1106 detected, revision 0x%02x\n", rev);
i2c_set_clientdata(i2c_client, priv);
node = dev->of_node;
if (!of_property_read_u32(node, "microchip,sensor-gain", &gain32)) {
if (is_power_of_2(gain32) && gain32 <= 8)
gain = ilog2(gain32);
else
dev_err(dev, "Invalid sensor-gain value %d\n", gain32);
}
BUILD_BUG_ON(ARRAY_SIZE(keycodes) != ARRAY_SIZE(priv->keycodes));
/* Provide some useful defaults */
for (i = 0; i < ARRAY_SIZE(keycodes); i++)
keycodes[i] = KEY_A + i;
of_property_read_u32_array(node, "linux,keycodes",
keycodes, ARRAY_SIZE(keycodes));
for (i = 0; i < ARRAY_SIZE(keycodes); i++)
priv->keycodes[i] = keycodes[i];
error = regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL,
CAP1106_REG_MAIN_CONTROL_GAIN_MASK,
gain << CAP1106_REG_MAIN_CONTROL_GAIN_SHIFT);
if (error)
return error;
/* Disable autorepeat. The Linux input system has its own handling. */
error = regmap_write(priv->regmap, CAP1106_REG_REPEAT_RATE, 0);
if (error)
return error;
priv->idev = devm_input_allocate_device(dev);
if (!priv->idev)
return -ENOMEM;
priv->idev->name = "CAP1106 capacitive touch sensor";
priv->idev->id.bustype = BUS_I2C;
priv->idev->evbit[0] = BIT_MASK(EV_KEY);
if (of_property_read_bool(node, "autorepeat"))
__set_bit(EV_REP, priv->idev->evbit);
for (i = 0; i < CAP1106_NUM_CHN; i++)
__set_bit(priv->keycodes[i], priv->idev->keybit);
__clear_bit(KEY_RESERVED, priv->idev->keybit);
priv->idev->keycode = priv->keycodes;
priv->idev->keycodesize = sizeof(priv->keycodes[0]);
priv->idev->keycodemax = ARRAY_SIZE(priv->keycodes);
priv->idev->id.vendor = CAP1106_MANUFACTURER_ID;
priv->idev->id.product = CAP1106_PRODUCT_ID;
priv->idev->id.version = rev;
priv->idev->open = cap1106_input_open;
priv->idev->close = cap1106_input_close;
input_set_drvdata(priv->idev, priv);
/*
* Put the device in deep sleep mode for now.
* ->open() will bring it back once the it is actually needed.
*/
cap1106_set_sleep(priv, true);
error = input_register_device(priv->idev);
if (error)
return error;
irq = irq_of_parse_and_map(node, 0);
if (!irq) {
dev_err(dev, "Unable to parse or map IRQ\n");
return -ENXIO;
}
error = devm_request_threaded_irq(dev, irq, NULL, cap1106_thread_func,
IRQF_ONESHOT, dev_name(dev), priv);
if (error)
return error;
return 0;
}
static const struct of_device_id cap1106_dt_ids[] = {
{ .compatible = "microchip,cap1106", },
{}
};
MODULE_DEVICE_TABLE(of, cap1106_dt_ids);
static const struct i2c_device_id cap1106_i2c_ids[] = {
{ "cap1106", 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, cap1106_i2c_ids);
static struct i2c_driver cap1106_i2c_driver = {
.driver = {
.name = "cap1106",
.owner = THIS_MODULE,
.of_match_table = cap1106_dt_ids,
},
.id_table = cap1106_i2c_ids,
.probe = cap1106_i2c_probe,
};
module_i2c_driver(cap1106_i2c_driver);
MODULE_ALIAS("platform:cap1106");
MODULE_DESCRIPTION("Microchip CAP1106 driver");
MODULE_AUTHOR("Daniel Mack <linux@zonque.org>");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,376 @@
/*
* Input driver for Microchip CAP11xx based capacitive touch sensors
*
* (c) 2014 Daniel Mack <linux@zonque.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/of_irq.h>
#include <linux/regmap.h>
#include <linux/i2c.h>
#include <linux/gpio/consumer.h>
#define CAP11XX_REG_MAIN_CONTROL 0x00
#define CAP11XX_REG_MAIN_CONTROL_GAIN_SHIFT (6)
#define CAP11XX_REG_MAIN_CONTROL_GAIN_MASK (0xc0)
#define CAP11XX_REG_MAIN_CONTROL_DLSEEP BIT(4)
#define CAP11XX_REG_GENERAL_STATUS 0x02
#define CAP11XX_REG_SENSOR_INPUT 0x03
#define CAP11XX_REG_NOISE_FLAG_STATUS 0x0a
#define CAP11XX_REG_SENOR_DELTA(X) (0x10 + (X))
#define CAP11XX_REG_SENSITIVITY_CONTROL 0x1f
#define CAP11XX_REG_CONFIG 0x20
#define CAP11XX_REG_SENSOR_ENABLE 0x21
#define CAP11XX_REG_SENSOR_CONFIG 0x22
#define CAP11XX_REG_SENSOR_CONFIG2 0x23
#define CAP11XX_REG_SAMPLING_CONFIG 0x24
#define CAP11XX_REG_CALIBRATION 0x26
#define CAP11XX_REG_INT_ENABLE 0x27
#define CAP11XX_REG_REPEAT_RATE 0x28
#define CAP11XX_REG_MT_CONFIG 0x2a
#define CAP11XX_REG_MT_PATTERN_CONFIG 0x2b
#define CAP11XX_REG_MT_PATTERN 0x2d
#define CAP11XX_REG_RECALIB_CONFIG 0x2f
#define CAP11XX_REG_SENSOR_THRESH(X) (0x30 + (X))
#define CAP11XX_REG_SENSOR_NOISE_THRESH 0x38
#define CAP11XX_REG_STANDBY_CHANNEL 0x40
#define CAP11XX_REG_STANDBY_CONFIG 0x41
#define CAP11XX_REG_STANDBY_SENSITIVITY 0x42
#define CAP11XX_REG_STANDBY_THRESH 0x43
#define CAP11XX_REG_CONFIG2 0x44
#define CAP11XX_REG_CONFIG2_ALT_POL BIT(6)
#define CAP11XX_REG_SENSOR_BASE_CNT(X) (0x50 + (X))
#define CAP11XX_REG_SENSOR_CALIB (0xb1 + (X))
#define CAP11XX_REG_SENSOR_CALIB_LSB1 0xb9
#define CAP11XX_REG_SENSOR_CALIB_LSB2 0xba
#define CAP11XX_REG_PRODUCT_ID 0xfd
#define CAP11XX_REG_MANUFACTURER_ID 0xfe
#define CAP11XX_REG_REVISION 0xff
#define CAP11XX_MANUFACTURER_ID 0x5d
struct cap11xx_priv {
struct regmap *regmap;
struct input_dev *idev;
/* config */
u32 keycodes[];
};
struct cap11xx_hw_model {
u8 product_id;
unsigned int num_channels;
};
enum {
CAP1106,
CAP1126,
CAP1188,
};
static const struct cap11xx_hw_model cap11xx_devices[] = {
[CAP1106] = { .product_id = 0x55, .num_channels = 6 },
[CAP1126] = { .product_id = 0x53, .num_channels = 6 },
[CAP1188] = { .product_id = 0x50, .num_channels = 8 },
};
static const struct reg_default cap11xx_reg_defaults[] = {
{ CAP11XX_REG_MAIN_CONTROL, 0x00 },
{ CAP11XX_REG_GENERAL_STATUS, 0x00 },
{ CAP11XX_REG_SENSOR_INPUT, 0x00 },
{ CAP11XX_REG_NOISE_FLAG_STATUS, 0x00 },
{ CAP11XX_REG_SENSITIVITY_CONTROL, 0x2f },
{ CAP11XX_REG_CONFIG, 0x20 },
{ CAP11XX_REG_SENSOR_ENABLE, 0x3f },
{ CAP11XX_REG_SENSOR_CONFIG, 0xa4 },
{ CAP11XX_REG_SENSOR_CONFIG2, 0x07 },
{ CAP11XX_REG_SAMPLING_CONFIG, 0x39 },
{ CAP11XX_REG_CALIBRATION, 0x00 },
{ CAP11XX_REG_INT_ENABLE, 0x3f },
{ CAP11XX_REG_REPEAT_RATE, 0x3f },
{ CAP11XX_REG_MT_CONFIG, 0x80 },
{ CAP11XX_REG_MT_PATTERN_CONFIG, 0x00 },
{ CAP11XX_REG_MT_PATTERN, 0x3f },
{ CAP11XX_REG_RECALIB_CONFIG, 0x8a },
{ CAP11XX_REG_SENSOR_THRESH(0), 0x40 },
{ CAP11XX_REG_SENSOR_THRESH(1), 0x40 },
{ CAP11XX_REG_SENSOR_THRESH(2), 0x40 },
{ CAP11XX_REG_SENSOR_THRESH(3), 0x40 },
{ CAP11XX_REG_SENSOR_THRESH(4), 0x40 },
{ CAP11XX_REG_SENSOR_THRESH(5), 0x40 },
{ CAP11XX_REG_SENSOR_NOISE_THRESH, 0x01 },
{ CAP11XX_REG_STANDBY_CHANNEL, 0x00 },
{ CAP11XX_REG_STANDBY_CONFIG, 0x39 },
{ CAP11XX_REG_STANDBY_SENSITIVITY, 0x02 },
{ CAP11XX_REG_STANDBY_THRESH, 0x40 },
{ CAP11XX_REG_CONFIG2, 0x40 },
{ CAP11XX_REG_SENSOR_CALIB_LSB1, 0x00 },
{ CAP11XX_REG_SENSOR_CALIB_LSB2, 0x00 },
};
static bool cap11xx_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case CAP11XX_REG_MAIN_CONTROL:
case CAP11XX_REG_SENSOR_INPUT:
case CAP11XX_REG_SENOR_DELTA(0):
case CAP11XX_REG_SENOR_DELTA(1):
case CAP11XX_REG_SENOR_DELTA(2):
case CAP11XX_REG_SENOR_DELTA(3):
case CAP11XX_REG_SENOR_DELTA(4):
case CAP11XX_REG_SENOR_DELTA(5):
case CAP11XX_REG_PRODUCT_ID:
case CAP11XX_REG_MANUFACTURER_ID:
case CAP11XX_REG_REVISION:
return true;
}
return false;
}
static const struct regmap_config cap11xx_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = CAP11XX_REG_REVISION,
.reg_defaults = cap11xx_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(cap11xx_reg_defaults),
.cache_type = REGCACHE_RBTREE,
.volatile_reg = cap11xx_volatile_reg,
};
static irqreturn_t cap11xx_thread_func(int irq_num, void *data)
{
struct cap11xx_priv *priv = data;
unsigned int status;
int ret, i;
/*
* Deassert interrupt. This needs to be done before reading the status
* registers, which will not carry valid values otherwise.
*/
ret = regmap_update_bits(priv->regmap, CAP11XX_REG_MAIN_CONTROL, 1, 0);
if (ret < 0)
goto out;
ret = regmap_read(priv->regmap, CAP11XX_REG_SENSOR_INPUT, &status);
if (ret < 0)
goto out;
for (i = 0; i < priv->idev->keycodemax; i++)
input_report_key(priv->idev, priv->keycodes[i],
status & (1 << i));
input_sync(priv->idev);
out:
return IRQ_HANDLED;
}
static int cap11xx_set_sleep(struct cap11xx_priv *priv, bool sleep)
{
return regmap_update_bits(priv->regmap, CAP11XX_REG_MAIN_CONTROL,
CAP11XX_REG_MAIN_CONTROL_DLSEEP,
sleep ? CAP11XX_REG_MAIN_CONTROL_DLSEEP : 0);
}
static int cap11xx_input_open(struct input_dev *idev)
{
struct cap11xx_priv *priv = input_get_drvdata(idev);
return cap11xx_set_sleep(priv, false);
}
static void cap11xx_input_close(struct input_dev *idev)
{
struct cap11xx_priv *priv = input_get_drvdata(idev);
cap11xx_set_sleep(priv, true);
}
static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
const struct i2c_device_id *id)
{
struct device *dev = &i2c_client->dev;
struct cap11xx_priv *priv;
struct device_node *node;
const struct cap11xx_hw_model *cap;
int i, error, irq, gain = 0;
unsigned int val, rev;
u32 gain32;
if (id->driver_data >= ARRAY_SIZE(cap11xx_devices)) {
dev_err(dev, "Invalid device ID %lu\n", id->driver_data);
return -EINVAL;
}
cap = &cap11xx_devices[id->driver_data];
if (!cap || !cap->num_channels) {
dev_err(dev, "Invalid device configuration\n");
return -EINVAL;
}
priv = devm_kzalloc(dev,
sizeof(*priv) +
cap->num_channels * sizeof(priv->keycodes[0]),
GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->regmap = devm_regmap_init_i2c(i2c_client, &cap11xx_regmap_config);
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);
error = regmap_read(priv->regmap, CAP11XX_REG_PRODUCT_ID, &val);
if (error)
return error;
if (val != cap->product_id) {
dev_err(dev, "Product ID: Got 0x%02x, expected 0x%02x\n",
val, cap->product_id);
return -ENXIO;
}
error = regmap_read(priv->regmap, CAP11XX_REG_MANUFACTURER_ID, &val);
if (error)
return error;
if (val != CAP11XX_MANUFACTURER_ID) {
dev_err(dev, "Manufacturer ID: Got 0x%02x, expected 0x%02x\n",
val, CAP11XX_MANUFACTURER_ID);
return -ENXIO;
}
error = regmap_read(priv->regmap, CAP11XX_REG_REVISION, &rev);
if (error < 0)
return error;
dev_info(dev, "CAP11XX detected, revision 0x%02x\n", rev);
i2c_set_clientdata(i2c_client, priv);
node = dev->of_node;
if (!of_property_read_u32(node, "microchip,sensor-gain", &gain32)) {
if (is_power_of_2(gain32) && gain32 <= 8)
gain = ilog2(gain32);
else
dev_err(dev, "Invalid sensor-gain value %d\n", gain32);
}
if (of_property_read_bool(node, "microchip,irq-active-high")) {
error = regmap_update_bits(priv->regmap, CAP11XX_REG_CONFIG2,
CAP11XX_REG_CONFIG2_ALT_POL, 0);
if (error)
return error;
}
/* Provide some useful defaults */
for (i = 0; i < cap->num_channels; i++)
priv->keycodes[i] = KEY_A + i;
of_property_read_u32_array(node, "linux,keycodes",
priv->keycodes, cap->num_channels);
error = regmap_update_bits(priv->regmap, CAP11XX_REG_MAIN_CONTROL,
CAP11XX_REG_MAIN_CONTROL_GAIN_MASK,
gain << CAP11XX_REG_MAIN_CONTROL_GAIN_SHIFT);
if (error)
return error;
/* Disable autorepeat. The Linux input system has its own handling. */
error = regmap_write(priv->regmap, CAP11XX_REG_REPEAT_RATE, 0);
if (error)
return error;
priv->idev = devm_input_allocate_device(dev);
if (!priv->idev)
return -ENOMEM;
priv->idev->name = "CAP11XX capacitive touch sensor";
priv->idev->id.bustype = BUS_I2C;
priv->idev->evbit[0] = BIT_MASK(EV_KEY);
if (of_property_read_bool(node, "autorepeat"))
__set_bit(EV_REP, priv->idev->evbit);
for (i = 0; i < cap->num_channels; i++)
__set_bit(priv->keycodes[i], priv->idev->keybit);
__clear_bit(KEY_RESERVED, priv->idev->keybit);
priv->idev->keycode = priv->keycodes;
priv->idev->keycodesize = sizeof(priv->keycodes[0]);
priv->idev->keycodemax = cap->num_channels;
priv->idev->id.vendor = CAP11XX_MANUFACTURER_ID;
priv->idev->id.product = cap->product_id;
priv->idev->id.version = rev;
priv->idev->open = cap11xx_input_open;
priv->idev->close = cap11xx_input_close;
input_set_drvdata(priv->idev, priv);
/*
* Put the device in deep sleep mode for now.
* ->open() will bring it back once the it is actually needed.
*/
cap11xx_set_sleep(priv, true);
error = input_register_device(priv->idev);
if (error)
return error;
irq = irq_of_parse_and_map(node, 0);
if (!irq) {
dev_err(dev, "Unable to parse or map IRQ\n");
return -ENXIO;
}
error = devm_request_threaded_irq(dev, irq, NULL, cap11xx_thread_func,
IRQF_ONESHOT, dev_name(dev), priv);
if (error)
return error;
return 0;
}
static const struct of_device_id cap11xx_dt_ids[] = {
{ .compatible = "microchip,cap1106", },
{ .compatible = "microchip,cap1126", },
{ .compatible = "microchip,cap1188", },
{}
};
MODULE_DEVICE_TABLE(of, cap11xx_dt_ids);
static const struct i2c_device_id cap11xx_i2c_ids[] = {
{ "cap1106", CAP1106 },
{ "cap1126", CAP1126 },
{ "cap1188", CAP1188 },
{}
};
MODULE_DEVICE_TABLE(i2c, cap11xx_i2c_ids);
static struct i2c_driver cap11xx_i2c_driver = {
.driver = {
.name = "cap11xx",
.owner = THIS_MODULE,
.of_match_table = cap11xx_dt_ids,
},
.id_table = cap11xx_i2c_ids,
.probe = cap11xx_i2c_probe,
};
module_i2c_driver(cap11xx_i2c_driver);
MODULE_ALIAS("platform:cap11xx");
MODULE_DESCRIPTION("Microchip CAP11XX driver");
MODULE_AUTHOR("Daniel Mack <linux@zonque.org>");
MODULE_LICENSE("GPL v2");

View File

@ -29,6 +29,7 @@
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/spinlock.h>
struct gpio_button_data {
@ -617,27 +618,31 @@ gpio_keys_get_devtree_pdata(struct device *dev)
i = 0;
for_each_child_of_node(node, pp) {
int gpio;
int gpio = -1;
enum of_gpio_flags flags;
if (!of_find_property(pp, "gpios", NULL)) {
pdata->nbuttons--;
dev_warn(dev, "Found button without gpios\n");
continue;
}
gpio = of_get_gpio_flags(pp, 0, &flags);
if (gpio < 0) {
error = gpio;
if (error != -EPROBE_DEFER)
dev_err(dev,
"Failed to get gpio flags, error: %d\n",
error);
return ERR_PTR(error);
}
button = &pdata->buttons[i++];
if (!of_find_property(pp, "gpios", NULL)) {
button->irq = irq_of_parse_and_map(pp, 0);
if (button->irq == 0) {
i--;
pdata->nbuttons--;
dev_warn(dev, "Found button without gpios or irqs\n");
continue;
}
} else {
gpio = of_get_gpio_flags(pp, 0, &flags);
if (gpio < 0) {
error = gpio;
if (error != -EPROBE_DEFER)
dev_err(dev,
"Failed to get gpio flags, error: %d\n",
error);
return ERR_PTR(error);
}
}
button->gpio = gpio;
button->active_low = flags & OF_GPIO_ACTIVE_LOW;

View File

@ -616,6 +616,8 @@ static ssize_t lm8323_set_disable(struct device *dev,
unsigned int i;
ret = kstrtouint(buf, 10, &i);
if (ret)
return ret;
mutex_lock(&lm->lock);
lm->kp_enabled = !i;

View File

@ -66,7 +66,6 @@
struct lpc32xx_kscan_drv {
struct input_dev *input;
struct clk *clk;
struct resource *iores;
void __iomem *kscan_base;
unsigned int irq;
@ -188,32 +187,27 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev)
return -EINVAL;
}
kscandat = kzalloc(sizeof(struct lpc32xx_kscan_drv), GFP_KERNEL);
if (!kscandat) {
dev_err(&pdev->dev, "failed to allocate memory\n");
kscandat = devm_kzalloc(&pdev->dev, sizeof(*kscandat),
GFP_KERNEL);
if (!kscandat)
return -ENOMEM;
}
error = lpc32xx_parse_dt(&pdev->dev, kscandat);
if (error) {
dev_err(&pdev->dev, "failed to parse device tree\n");
goto err_free_mem;
return error;
}
keymap_size = sizeof(kscandat->keymap[0]) *
(kscandat->matrix_sz << kscandat->row_shift);
kscandat->keymap = kzalloc(keymap_size, GFP_KERNEL);
if (!kscandat->keymap) {
dev_err(&pdev->dev, "could not allocate memory for keymap\n");
error = -ENOMEM;
goto err_free_mem;
}
kscandat->keymap = devm_kzalloc(&pdev->dev, keymap_size, GFP_KERNEL);
if (!kscandat->keymap)
return -ENOMEM;
kscandat->input = input = input_allocate_device();
kscandat->input = input = devm_input_allocate_device(&pdev->dev);
if (!input) {
dev_err(&pdev->dev, "failed to allocate input device\n");
error = -ENOMEM;
goto err_free_keymap;
return -ENOMEM;
}
/* Setup key input */
@ -234,39 +228,26 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev)
kscandat->keymap, kscandat->input);
if (error) {
dev_err(&pdev->dev, "failed to build keymap\n");
goto err_free_input;
return error;
}
input_set_drvdata(kscandat->input, kscandat);
kscandat->iores = request_mem_region(res->start, resource_size(res),
pdev->name);
if (!kscandat->iores) {
dev_err(&pdev->dev, "failed to request I/O memory\n");
error = -EBUSY;
goto err_free_input;
}
kscandat->kscan_base = ioremap(kscandat->iores->start,
resource_size(kscandat->iores));
if (!kscandat->kscan_base) {
dev_err(&pdev->dev, "failed to remap I/O memory\n");
error = -EBUSY;
goto err_release_memregion;
}
kscandat->kscan_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(kscandat->kscan_base))
return PTR_ERR(kscandat->kscan_base);
/* Get the key scanner clock */
kscandat->clk = clk_get(&pdev->dev, NULL);
kscandat->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(kscandat->clk)) {
dev_err(&pdev->dev, "failed to get clock\n");
error = PTR_ERR(kscandat->clk);
goto err_unmap;
return PTR_ERR(kscandat->clk);
}
/* Configure the key scanner */
error = clk_prepare_enable(kscandat->clk);
if (error)
goto err_clk_put;
return error;
writel(kscandat->deb_clks, LPC32XX_KS_DEB(kscandat->kscan_base));
writel(kscandat->scan_delay, LPC32XX_KS_SCAN_CTL(kscandat->kscan_base));
@ -277,52 +258,20 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev)
writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
clk_disable_unprepare(kscandat->clk);
error = request_irq(irq, lpc32xx_kscan_irq, 0, pdev->name, kscandat);
error = devm_request_irq(&pdev->dev, irq, lpc32xx_kscan_irq, 0,
pdev->name, kscandat);
if (error) {
dev_err(&pdev->dev, "failed to request irq\n");
goto err_clk_put;
return error;
}
error = input_register_device(kscandat->input);
if (error) {
dev_err(&pdev->dev, "failed to register input device\n");
goto err_free_irq;
return error;
}
platform_set_drvdata(pdev, kscandat);
return 0;
err_free_irq:
free_irq(irq, kscandat);
err_clk_put:
clk_put(kscandat->clk);
err_unmap:
iounmap(kscandat->kscan_base);
err_release_memregion:
release_mem_region(kscandat->iores->start,
resource_size(kscandat->iores));
err_free_input:
input_free_device(kscandat->input);
err_free_keymap:
kfree(kscandat->keymap);
err_free_mem:
kfree(kscandat);
return error;
}
static int lpc32xx_kscan_remove(struct platform_device *pdev)
{
struct lpc32xx_kscan_drv *kscandat = platform_get_drvdata(pdev);
free_irq(platform_get_irq(pdev, 0), kscandat);
clk_put(kscandat->clk);
iounmap(kscandat->kscan_base);
release_mem_region(kscandat->iores->start,
resource_size(kscandat->iores));
input_unregister_device(kscandat->input);
kfree(kscandat->keymap);
kfree(kscandat);
return 0;
}
@ -378,7 +327,6 @@ MODULE_DEVICE_TABLE(of, lpc32xx_kscan_match);
static struct platform_driver lpc32xx_kscan_driver = {
.probe = lpc32xx_kscan_probe,
.remove = lpc32xx_kscan_remove,
.driver = {
.name = DRV_NAME,
.pm = &lpc32xx_kscan_pm_ops,

View File

@ -214,13 +214,14 @@ static int mpr_touchkey_probe(struct i2c_client *client,
return -EINVAL;
}
mpr121 = kzalloc(sizeof(struct mpr121_touchkey), GFP_KERNEL);
input_dev = input_allocate_device();
if (!mpr121 || !input_dev) {
dev_err(&client->dev, "Failed to allocate memory\n");
error = -ENOMEM;
goto err_free_mem;
}
mpr121 = devm_kzalloc(&client->dev, sizeof(*mpr121),
GFP_KERNEL);
if (!mpr121)
return -ENOMEM;
input_dev = devm_input_allocate_device(&client->dev);
if (!input_dev)
return -ENOMEM;
mpr121->client = client;
mpr121->input_dev = input_dev;
@ -243,43 +244,25 @@ static int mpr_touchkey_probe(struct i2c_client *client,
error = mpr121_phys_init(pdata, mpr121, client);
if (error) {
dev_err(&client->dev, "Failed to init register\n");
goto err_free_mem;
return error;
}
error = request_threaded_irq(client->irq, NULL,
error = devm_request_threaded_irq(&client->dev, client->irq, NULL,
mpr_touchkey_interrupt,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
client->dev.driver->name, mpr121);
if (error) {
dev_err(&client->dev, "Failed to register interrupt\n");
goto err_free_mem;
return error;
}
error = input_register_device(input_dev);
if (error)
goto err_free_irq;
return error;
i2c_set_clientdata(client, mpr121);
device_init_wakeup(&client->dev, pdata->wakeup);
return 0;
err_free_irq:
free_irq(client->irq, mpr121);
err_free_mem:
input_free_device(input_dev);
kfree(mpr121);
return error;
}
static int mpr_touchkey_remove(struct i2c_client *client)
{
struct mpr121_touchkey *mpr121 = i2c_get_clientdata(client);
free_irq(client->irq, mpr121);
input_unregister_device(mpr121->input_dev);
kfree(mpr121);
return 0;
}
@ -327,7 +310,6 @@ static struct i2c_driver mpr_touchkey_driver = {
},
.id_table = mpr121_id,
.probe = mpr_touchkey_probe,
.remove = mpr_touchkey_remove,
};
module_i2c_driver(mpr_touchkey_driver);

View File

@ -741,37 +741,27 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
return -ENXIO;
}
keypad = kzalloc(sizeof(struct pxa27x_keypad), GFP_KERNEL);
input_dev = input_allocate_device();
if (!keypad || !input_dev) {
dev_err(&pdev->dev, "failed to allocate memory\n");
error = -ENOMEM;
goto failed_free;
}
keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad),
GFP_KERNEL);
if (!keypad)
return -ENOMEM;
input_dev = devm_input_allocate_device(&pdev->dev);
if (!input_dev)
return -ENOMEM;
keypad->pdata = pdata;
keypad->input_dev = input_dev;
keypad->irq = irq;
res = request_mem_region(res->start, resource_size(res), pdev->name);
if (res == NULL) {
dev_err(&pdev->dev, "failed to request I/O memory\n");
error = -EBUSY;
goto failed_free;
}
keypad->mmio_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(keypad->mmio_base))
return PTR_ERR(keypad->mmio_base);
keypad->mmio_base = ioremap(res->start, resource_size(res));
if (keypad->mmio_base == NULL) {
dev_err(&pdev->dev, "failed to remap I/O memory\n");
error = -ENXIO;
goto failed_free_mem;
}
keypad->clk = clk_get(&pdev->dev, NULL);
keypad->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(keypad->clk)) {
dev_err(&pdev->dev, "failed to get keypad clock\n");
error = PTR_ERR(keypad->clk);
goto failed_free_io;
return PTR_ERR(keypad->clk);
}
input_dev->name = pdev->name;
@ -802,7 +792,7 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
}
if (error) {
dev_err(&pdev->dev, "failed to build keycode\n");
goto failed_put_clk;
return error;
}
keypad->row_shift = get_count_order(pdata->matrix_key_cols);
@ -812,61 +802,26 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
input_dev->evbit[0] |= BIT_MASK(EV_REL);
}
error = request_irq(irq, pxa27x_keypad_irq_handler, 0,
pdev->name, keypad);
error = devm_request_irq(&pdev->dev, irq, pxa27x_keypad_irq_handler,
0, pdev->name, keypad);
if (error) {
dev_err(&pdev->dev, "failed to request IRQ\n");
goto failed_put_clk;
return error;
}
/* Register the input device */
error = input_register_device(input_dev);
if (error) {
dev_err(&pdev->dev, "failed to register input device\n");
goto failed_free_irq;
return error;
}
platform_set_drvdata(pdev, keypad);
device_init_wakeup(&pdev->dev, 1);
return 0;
failed_free_irq:
free_irq(irq, keypad);
failed_put_clk:
clk_put(keypad->clk);
failed_free_io:
iounmap(keypad->mmio_base);
failed_free_mem:
release_mem_region(res->start, resource_size(res));
failed_free:
input_free_device(input_dev);
kfree(keypad);
return error;
}
static int pxa27x_keypad_remove(struct platform_device *pdev)
{
struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
struct resource *res;
free_irq(keypad->irq, keypad);
clk_put(keypad->clk);
input_unregister_device(keypad->input_dev);
iounmap(keypad->mmio_base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, resource_size(res));
kfree(keypad);
return 0;
}
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:pxa27x-keypad");
#ifdef CONFIG_OF
static const struct of_device_id pxa27x_keypad_dt_match[] = {
{ .compatible = "marvell,pxa27x-keypad" },
@ -877,7 +832,6 @@ MODULE_DEVICE_TABLE(of, pxa27x_keypad_dt_match);
static struct platform_driver pxa27x_keypad_driver = {
.probe = pxa27x_keypad_probe,
.remove = pxa27x_keypad_remove,
.driver = {
.name = "pxa27x-keypad",
.of_match_table = of_match_ptr(pxa27x_keypad_dt_match),
@ -888,3 +842,5 @@ module_platform_driver(pxa27x_keypad_driver);
MODULE_DESCRIPTION("PXA27x Keypad Controller Driver");
MODULE_LICENSE("GPL");
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:pxa27x-keypad");

View File

@ -112,8 +112,7 @@ static int pm860x_onkey_probe(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int pm860x_onkey_suspend(struct device *dev)
static int __maybe_unused pm860x_onkey_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
@ -122,7 +121,7 @@ static int pm860x_onkey_suspend(struct device *dev)
chip->wakeup_flag |= 1 << PM8607_IRQ_ONKEY;
return 0;
}
static int pm860x_onkey_resume(struct device *dev)
static int __maybe_unused pm860x_onkey_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
@ -131,7 +130,6 @@ static int pm860x_onkey_resume(struct device *dev)
chip->wakeup_flag &= ~(1 << PM8607_IRQ_ONKEY);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(pm860x_onkey_pm_ops, pm860x_onkey_suspend, pm860x_onkey_resume);

View File

@ -13,17 +13,15 @@
#include <linux/pm.h>
#include "ad714x.h"
#ifdef CONFIG_PM_SLEEP
static int ad714x_i2c_suspend(struct device *dev)
static int __maybe_unused ad714x_i2c_suspend(struct device *dev)
{
return ad714x_disable(i2c_get_clientdata(to_i2c_client(dev)));
}
static int ad714x_i2c_resume(struct device *dev)
static int __maybe_unused ad714x_i2c_resume(struct device *dev)
{
return ad714x_enable(i2c_get_clientdata(to_i2c_client(dev)));
}
#endif
static SIMPLE_DEV_PM_OPS(ad714x_i2c_pm, ad714x_i2c_suspend, ad714x_i2c_resume);

View File

@ -16,17 +16,15 @@
#define AD714x_SPI_CMD_PREFIX 0xE000 /* bits 15:11 */
#define AD714x_SPI_READ BIT(10)
#ifdef CONFIG_PM_SLEEP
static int ad714x_spi_suspend(struct device *dev)
static int __maybe_unused ad714x_spi_suspend(struct device *dev)
{
return ad714x_disable(spi_get_drvdata(to_spi_device(dev)));
}
static int ad714x_spi_resume(struct device *dev)
static int __maybe_unused ad714x_spi_resume(struct device *dev)
{
return ad714x_enable(spi_get_drvdata(to_spi_device(dev)));
}
#endif
static SIMPLE_DEV_PM_OPS(ad714x_spi_pm, ad714x_spi_suspend, ad714x_spi_resume);

View File

@ -105,8 +105,7 @@ static int adxl34x_i2c_remove(struct i2c_client *client)
return adxl34x_remove(ac);
}
#ifdef CONFIG_PM_SLEEP
static int adxl34x_i2c_suspend(struct device *dev)
static int __maybe_unused adxl34x_i2c_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct adxl34x *ac = i2c_get_clientdata(client);
@ -116,7 +115,7 @@ static int adxl34x_i2c_suspend(struct device *dev)
return 0;
}
static int adxl34x_i2c_resume(struct device *dev)
static int __maybe_unused adxl34x_i2c_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct adxl34x *ac = i2c_get_clientdata(client);
@ -125,7 +124,6 @@ static int adxl34x_i2c_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(adxl34x_i2c_pm, adxl34x_i2c_suspend,
adxl34x_i2c_resume);

View File

@ -94,8 +94,7 @@ static int adxl34x_spi_remove(struct spi_device *spi)
return adxl34x_remove(ac);
}
#ifdef CONFIG_PM_SLEEP
static int adxl34x_spi_suspend(struct device *dev)
static int __maybe_unused adxl34x_spi_suspend(struct device *dev)
{
struct spi_device *spi = to_spi_device(dev);
struct adxl34x *ac = spi_get_drvdata(spi);
@ -105,7 +104,7 @@ static int adxl34x_spi_suspend(struct device *dev)
return 0;
}
static int adxl34x_spi_resume(struct device *dev)
static int __maybe_unused adxl34x_spi_resume(struct device *dev)
{
struct spi_device *spi = to_spi_device(dev);
struct adxl34x *ac = spi_get_drvdata(spi);
@ -114,7 +113,6 @@ static int adxl34x_spi_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(adxl34x_spi_pm, adxl34x_spi_suspend,
adxl34x_spi_resume);

View File

@ -639,8 +639,7 @@ static int drv260x_probe(struct i2c_client *client,
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int drv260x_suspend(struct device *dev)
static int __maybe_unused drv260x_suspend(struct device *dev)
{
struct drv260x_data *haptics = dev_get_drvdata(dev);
int ret = 0;
@ -672,7 +671,7 @@ out:
return ret;
}
static int drv260x_resume(struct device *dev)
static int __maybe_unused drv260x_resume(struct device *dev)
{
struct drv260x_data *haptics = dev_get_drvdata(dev);
int ret = 0;
@ -702,7 +701,6 @@ out:
mutex_unlock(&haptics->input_dev->mutex);
return ret;
}
#endif
static SIMPLE_DEV_PM_OPS(drv260x_pm_ops, drv260x_suspend, drv260x_resume);

View File

@ -406,8 +406,7 @@ static int drv2667_probe(struct i2c_client *client,
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int drv2667_suspend(struct device *dev)
static int __maybe_unused drv2667_suspend(struct device *dev)
{
struct drv2667_data *haptics = dev_get_drvdata(dev);
int ret = 0;
@ -436,7 +435,7 @@ out:
return ret;
}
static int drv2667_resume(struct device *dev)
static int __maybe_unused drv2667_resume(struct device *dev)
{
struct drv2667_data *haptics = dev_get_drvdata(dev);
int ret = 0;
@ -464,7 +463,6 @@ out:
mutex_unlock(&haptics->input_dev->mutex);
return ret;
}
#endif
static SIMPLE_DEV_PM_OPS(drv2667_pm_ops, drv2667_suspend, drv2667_resume);

View File

@ -225,8 +225,7 @@ static int gp2a_remove(struct i2c_client *client)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int gp2a_suspend(struct device *dev)
static int __maybe_unused gp2a_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct gp2a_data *dt = i2c_get_clientdata(client);
@ -244,7 +243,7 @@ static int gp2a_suspend(struct device *dev)
return retval;
}
static int gp2a_resume(struct device *dev)
static int __maybe_unused gp2a_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct gp2a_data *dt = i2c_get_clientdata(client);
@ -261,7 +260,6 @@ static int gp2a_resume(struct device *dev)
return retval;
}
#endif
static SIMPLE_DEV_PM_OPS(gp2a_pm, gp2a_suspend, gp2a_resume);

View File

@ -1851,7 +1851,7 @@ static int ims_pcu_identify_type(struct ims_pcu *pcu, u8 *device_id)
static int ims_pcu_init_application_mode(struct ims_pcu *pcu)
{
static atomic_t device_no = ATOMIC_INIT(0);
static atomic_t device_no = ATOMIC_INIT(-1);
const struct ims_pcu_device_info *info;
int error;
@ -1882,7 +1882,7 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)
}
/* Device appears to be operable, complete initialization */
pcu->device_no = atomic_inc_return(&device_no) - 1;
pcu->device_no = atomic_inc_return(&device_no);
/*
* PCU-B devices, both GEN_1 and GEN_2 do not have OFN sensor

View File

@ -615,8 +615,7 @@ static int kxtj9_remove(struct i2c_client *client)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int kxtj9_suspend(struct device *dev)
static int __maybe_unused kxtj9_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct kxtj9_data *tj9 = i2c_get_clientdata(client);
@ -631,7 +630,7 @@ static int kxtj9_suspend(struct device *dev)
return 0;
}
static int kxtj9_resume(struct device *dev)
static int __maybe_unused kxtj9_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct kxtj9_data *tj9 = i2c_get_clientdata(client);
@ -646,7 +645,6 @@ static int kxtj9_resume(struct device *dev)
mutex_unlock(&input_dev->mutex);
return retval;
}
#endif
static SIMPLE_DEV_PM_OPS(kxtj9_pm_ops, kxtj9_suspend, kxtj9_resume);

View File

@ -309,8 +309,7 @@ static int max77693_haptic_probe(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int max77693_haptic_suspend(struct device *dev)
static int __maybe_unused max77693_haptic_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct max77693_haptic *haptic = platform_get_drvdata(pdev);
@ -323,7 +322,7 @@ static int max77693_haptic_suspend(struct device *dev)
return 0;
}
static int max77693_haptic_resume(struct device *dev)
static int __maybe_unused max77693_haptic_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct max77693_haptic *haptic = platform_get_drvdata(pdev);
@ -335,7 +334,6 @@ static int max77693_haptic_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(max77693_haptic_pm_ops,
max77693_haptic_suspend, max77693_haptic_resume);

View File

@ -133,8 +133,7 @@ static int max8925_onkey_probe(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int max8925_onkey_suspend(struct device *dev)
static int __maybe_unused max8925_onkey_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct max8925_onkey_info *info = platform_get_drvdata(pdev);
@ -148,7 +147,7 @@ static int max8925_onkey_suspend(struct device *dev)
return 0;
}
static int max8925_onkey_resume(struct device *dev)
static int __maybe_unused max8925_onkey_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct max8925_onkey_info *info = platform_get_drvdata(pdev);
@ -161,7 +160,6 @@ static int max8925_onkey_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(max8925_onkey_pm_ops, max8925_onkey_suspend, max8925_onkey_resume);

View File

@ -378,8 +378,7 @@ static int max8997_haptic_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int max8997_haptic_suspend(struct device *dev)
static int __maybe_unused max8997_haptic_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct max8997_haptic *chip = platform_get_drvdata(pdev);
@ -388,7 +387,6 @@ static int max8997_haptic_suspend(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(max8997_haptic_pm_ops, max8997_haptic_suspend, NULL);

View File

@ -260,7 +260,6 @@ static int palmas_pwron_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
/**
* palmas_pwron_suspend() - suspend handler
* @dev: power button device
@ -269,7 +268,7 @@ static int palmas_pwron_remove(struct platform_device *pdev)
*
* Return: 0
*/
static int palmas_pwron_suspend(struct device *dev)
static int __maybe_unused palmas_pwron_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct palmas_pwron *pwron = platform_get_drvdata(pdev);
@ -290,7 +289,7 @@ static int palmas_pwron_suspend(struct device *dev)
*
* Return: 0
*/
static int palmas_pwron_resume(struct device *dev)
static int __maybe_unused palmas_pwron_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct palmas_pwron *pwron = platform_get_drvdata(pdev);
@ -300,7 +299,6 @@ static int palmas_pwron_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(palmas_pwron_pm,
palmas_pwron_suspend, palmas_pwron_resume);

View File

@ -199,8 +199,7 @@ static int pm8xxx_vib_probe(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int pm8xxx_vib_suspend(struct device *dev)
static int __maybe_unused pm8xxx_vib_suspend(struct device *dev)
{
struct pm8xxx_vib *vib = dev_get_drvdata(dev);
@ -209,7 +208,6 @@ static int pm8xxx_vib_suspend(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL);

View File

@ -53,8 +53,7 @@ static irqreturn_t pwrkey_release_irq(int irq, void *_pwr)
return IRQ_HANDLED;
}
#ifdef CONFIG_PM_SLEEP
static int pmic8xxx_pwrkey_suspend(struct device *dev)
static int __maybe_unused pmic8xxx_pwrkey_suspend(struct device *dev)
{
struct pmic8xxx_pwrkey *pwrkey = dev_get_drvdata(dev);
@ -64,7 +63,7 @@ static int pmic8xxx_pwrkey_suspend(struct device *dev)
return 0;
}
static int pmic8xxx_pwrkey_resume(struct device *dev)
static int __maybe_unused pmic8xxx_pwrkey_resume(struct device *dev)
{
struct pmic8xxx_pwrkey *pwrkey = dev_get_drvdata(dev);
@ -73,7 +72,6 @@ static int pmic8xxx_pwrkey_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(pm8xxx_pwr_key_pm_ops,
pmic8xxx_pwrkey_suspend, pmic8xxx_pwrkey_resume);

View File

@ -144,8 +144,7 @@ static int pwm_beeper_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int pwm_beeper_suspend(struct device *dev)
static int __maybe_unused pwm_beeper_suspend(struct device *dev)
{
struct pwm_beeper *beeper = dev_get_drvdata(dev);
@ -155,7 +154,7 @@ static int pwm_beeper_suspend(struct device *dev)
return 0;
}
static int pwm_beeper_resume(struct device *dev)
static int __maybe_unused pwm_beeper_resume(struct device *dev)
{
struct pwm_beeper *beeper = dev_get_drvdata(dev);
@ -170,6 +169,7 @@ static int pwm_beeper_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(pwm_beeper_pm_ops,
pwm_beeper_suspend, pwm_beeper_resume);
#ifdef CONFIG_PM_SLEEP
#define PWM_BEEPER_PM_OPS (&pwm_beeper_pm_ops)
#else
#define PWM_BEEPER_PM_OPS NULL

View File

@ -179,8 +179,7 @@ static int sirfsoc_pwrc_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int sirfsoc_pwrc_resume(struct device *dev)
static int __maybe_unused sirfsoc_pwrc_resume(struct device *dev)
{
struct sirfsoc_pwrc_drvdata *pwrcdrv = dev_get_drvdata(dev);
struct input_dev *input = pwrcdrv->input;
@ -196,7 +195,6 @@ static int sirfsoc_pwrc_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, sirfsoc_pwrc_resume);

View File

@ -157,8 +157,7 @@ static void twl4030_vibra_close(struct input_dev *input)
}
/*** Module ***/
#ifdef CONFIG_PM_SLEEP
static int twl4030_vibra_suspend(struct device *dev)
static int __maybe_unused twl4030_vibra_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct vibra_info *info = platform_get_drvdata(pdev);
@ -169,12 +168,11 @@ static int twl4030_vibra_suspend(struct device *dev)
return 0;
}
static int twl4030_vibra_resume(struct device *dev)
static int __maybe_unused twl4030_vibra_resume(struct device *dev)
{
vibra_disable_leds();
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
twl4030_vibra_suspend, twl4030_vibra_resume);

View File

@ -236,8 +236,7 @@ static void twl6040_vibra_close(struct input_dev *input)
mutex_unlock(&info->mutex);
}
#ifdef CONFIG_PM_SLEEP
static int twl6040_vibra_suspend(struct device *dev)
static int __maybe_unused twl6040_vibra_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct vibra_info *info = platform_get_drvdata(pdev);
@ -251,7 +250,6 @@ static int twl6040_vibra_suspend(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL);

View File

@ -215,6 +215,36 @@ config MOUSE_CYAPA
To compile this driver as a module, choose M here: the module will be
called cyapa.
config MOUSE_ELAN_I2C
tristate "ELAN I2C Touchpad support"
depends on I2C
help
This driver adds support for Elan I2C/SMbus Trackpads.
Say Y here if you have a ELAN I2C/SMbus Touchpad.
To compile this driver as a module, choose M here: the module will be
called elan_i2c.
config MOUSE_ELAN_I2C_I2C
bool "Enable I2C support"
depends on MOUSE_ELAN_I2C
default y
help
Say Y here if Elan Touchpad in your system is connected to
a standard I2C controller.
If unsure, say Y.
config MOUSE_ELAN_I2C_SMBUS
bool "Enable SMbus support"
depends on MOUSE_ELAN_I2C
help
Say Y here if Elan Touchpad in your system is connected to
a SMbus adapter.
If unsure, say Y.
config MOUSE_INPORT
tristate "InPort/MS/ATIXL busmouse"
depends on ISA

View File

@ -9,6 +9,7 @@ obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o
obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o
obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o
obj-$(CONFIG_MOUSE_CYAPA) += cyapa.o
obj-$(CONFIG_MOUSE_ELAN_I2C) += elan_i2c.o
obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o
obj-$(CONFIG_MOUSE_INPORT) += inport.o
obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o
@ -34,3 +35,7 @@ psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o
psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o
psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o
psmouse-$(CONFIG_MOUSE_PS2_CYPRESS) += cypress_ps2.o
elan_i2c-objs := elan_i2c_core.o
elan_i2c-$(CONFIG_MOUSE_ELAN_I2C_I2C) += elan_i2c_i2c.o
elan_i2c-$(CONFIG_MOUSE_ELAN_I2C_SMBUS) += elan_i2c_smbus.o

View File

@ -6,7 +6,7 @@
* Daniel Kurtz <djkurtz@chromium.org>
* Benson Leung <bleung@chromium.org>
*
* Copyright (C) 2011-2012 Cypress Semiconductor, Inc.
* Copyright (C) 2011-2014 Cypress Semiconductor, Inc.
* Copyright (C) 2011-2012 Google, Inc.
*
* This file is subject to the terms and conditions of the GNU General Public
@ -206,7 +206,6 @@ struct cyapa {
struct i2c_client *client;
struct input_dev *input;
char phys[32]; /* device physical location */
int irq;
bool irq_wake; /* irq wake is enabled */
bool smbus;
@ -422,8 +421,8 @@ static ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values)
*/
static int cyapa_get_state(struct cyapa *cyapa)
{
int ret;
u8 status[BL_STATUS_SIZE];
int error;
cyapa->state = CYAPA_STATE_NO_DEVICE;
@ -433,18 +432,18 @@ static int cyapa_get_state(struct cyapa *cyapa)
* If the device is in operation mode, this will be the DATA regs.
*
*/
ret = cyapa_i2c_reg_read_block(cyapa, BL_HEAD_OFFSET, BL_STATUS_SIZE,
status);
error = cyapa_i2c_reg_read_block(cyapa, BL_HEAD_OFFSET, BL_STATUS_SIZE,
status);
/*
* On smbus systems in OP mode, the i2c_reg_read will fail with
* -ETIMEDOUT. In this case, try again using the smbus equivalent
* command. This should return a BL_HEAD indicating CYAPA_STATE_OP.
*/
if (cyapa->smbus && (ret == -ETIMEDOUT || ret == -ENXIO))
ret = cyapa_read_block(cyapa, CYAPA_CMD_BL_STATUS, status);
if (cyapa->smbus && (error == -ETIMEDOUT || error == -ENXIO))
error = cyapa_read_block(cyapa, CYAPA_CMD_BL_STATUS, status);
if (ret != BL_STATUS_SIZE)
if (error != BL_STATUS_SIZE)
goto error;
if ((status[REG_OP_STATUS] & OP_STATUS_SRC) == OP_STATUS_SRC) {
@ -454,7 +453,7 @@ static int cyapa_get_state(struct cyapa *cyapa)
cyapa->state = CYAPA_STATE_OP;
break;
default:
ret = -EAGAIN;
error = -EAGAIN;
goto error;
}
} else {
@ -468,7 +467,7 @@ static int cyapa_get_state(struct cyapa *cyapa)
return 0;
error:
return (ret < 0) ? ret : -EAGAIN;
return (error < 0) ? error : -EAGAIN;
}
/*
@ -487,31 +486,31 @@ error:
*/
static int cyapa_poll_state(struct cyapa *cyapa, unsigned int timeout)
{
int ret;
int error;
int tries = timeout / 100;
ret = cyapa_get_state(cyapa);
while ((ret || cyapa->state >= CYAPA_STATE_BL_BUSY) && tries--) {
error = cyapa_get_state(cyapa);
while ((error || cyapa->state >= CYAPA_STATE_BL_BUSY) && tries--) {
msleep(100);
ret = cyapa_get_state(cyapa);
error = cyapa_get_state(cyapa);
}
return (ret == -EAGAIN || ret == -ETIMEDOUT) ? -ETIMEDOUT : ret;
return (error == -EAGAIN || error == -ETIMEDOUT) ? -ETIMEDOUT : error;
}
static int cyapa_bl_deactivate(struct cyapa *cyapa)
{
int ret;
int error;
ret = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_deactivate),
bl_deactivate);
if (ret < 0)
return ret;
error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_deactivate),
bl_deactivate);
if (error)
return error;
/* wait for bootloader to switch to idle state; should take < 100ms */
msleep(100);
ret = cyapa_poll_state(cyapa, 500);
if (ret < 0)
return ret;
error = cyapa_poll_state(cyapa, 500);
if (error)
return error;
if (cyapa->state != CYAPA_STATE_BL_IDLE)
return -EAGAIN;
return 0;
@ -532,11 +531,11 @@ static int cyapa_bl_deactivate(struct cyapa *cyapa)
*/
static int cyapa_bl_exit(struct cyapa *cyapa)
{
int ret;
int error;
ret = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_exit), bl_exit);
if (ret < 0)
return ret;
error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_exit), bl_exit);
if (error)
return error;
/*
* Wait for bootloader to exit, and operation mode to start.
@ -548,9 +547,9 @@ static int cyapa_bl_exit(struct cyapa *cyapa)
* updated to new firmware, it must first calibrate its sensors, which
* can take up to an additional 2 seconds.
*/
ret = cyapa_poll_state(cyapa, 2000);
if (ret < 0)
return ret;
error = cyapa_poll_state(cyapa, 2000);
if (error < 0)
return error;
if (cyapa->state != CYAPA_STATE_OP)
return -EAGAIN;
@ -577,10 +576,13 @@ static int cyapa_set_power_mode(struct cyapa *cyapa, u8 power_mode)
power = ret & ~PWR_MODE_MASK;
power |= power_mode & PWR_MODE_MASK;
ret = cyapa_write_byte(cyapa, CYAPA_CMD_POWER_MODE, power);
if (ret < 0)
if (ret < 0) {
dev_err(dev, "failed to set power_mode 0x%02x err = %d\n",
power_mode, ret);
return ret;
return ret;
}
return 0;
}
static int cyapa_get_query_data(struct cyapa *cyapa)
@ -637,28 +639,28 @@ static int cyapa_check_is_operational(struct cyapa *cyapa)
{
struct device *dev = &cyapa->client->dev;
static const char unique_str[] = "CYTRA";
int ret;
int error;
ret = cyapa_poll_state(cyapa, 2000);
if (ret < 0)
return ret;
error = cyapa_poll_state(cyapa, 2000);
if (error)
return error;
switch (cyapa->state) {
case CYAPA_STATE_BL_ACTIVE:
ret = cyapa_bl_deactivate(cyapa);
if (ret)
return ret;
error = cyapa_bl_deactivate(cyapa);
if (error)
return error;
/* Fallthrough state */
case CYAPA_STATE_BL_IDLE:
ret = cyapa_bl_exit(cyapa);
if (ret)
return ret;
error = cyapa_bl_exit(cyapa);
if (error)
return error;
/* Fallthrough state */
case CYAPA_STATE_OP:
ret = cyapa_get_query_data(cyapa);
if (ret < 0)
return ret;
error = cyapa_get_query_data(cyapa);
if (error)
return error;
/* only support firmware protocol gen3 */
if (cyapa->gen != CYAPA_GEN3) {
@ -753,18 +755,42 @@ static u8 cyapa_check_adapter_functionality(struct i2c_client *client)
return ret;
}
static int cyapa_open(struct input_dev *input)
{
struct cyapa *cyapa = input_get_drvdata(input);
struct i2c_client *client = cyapa->client;
int error;
error = cyapa_set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE);
if (error) {
dev_err(&client->dev, "set active power failed: %d\n", error);
return error;
}
enable_irq(client->irq);
return 0;
}
static void cyapa_close(struct input_dev *input)
{
struct cyapa *cyapa = input_get_drvdata(input);
disable_irq(cyapa->client->irq);
cyapa_set_power_mode(cyapa, PWR_MODE_OFF);
}
static int cyapa_create_input_dev(struct cyapa *cyapa)
{
struct device *dev = &cyapa->client->dev;
int ret;
struct input_dev *input;
int error;
if (!cyapa->physical_size_x || !cyapa->physical_size_y)
return -EINVAL;
input = cyapa->input = input_allocate_device();
input = devm_input_allocate_device(dev);
if (!input) {
dev_err(dev, "allocate memory for input device failed\n");
dev_err(dev, "failed to allocate memory for input device.\n");
return -ENOMEM;
}
@ -772,14 +798,17 @@ static int cyapa_create_input_dev(struct cyapa *cyapa)
input->phys = cyapa->phys;
input->id.bustype = BUS_I2C;
input->id.version = 1;
input->id.product = 0; /* means any product in eventcomm. */
input->id.product = 0; /* Means any product in eventcomm. */
input->dev.parent = &cyapa->client->dev;
input->open = cyapa_open;
input->close = cyapa_close;
input_set_drvdata(input, cyapa);
__set_bit(EV_ABS, input->evbit);
/* finger position */
/* Finger position */
input_set_abs_params(input, ABS_MT_POSITION_X, 0, cyapa->max_abs_x, 0,
0);
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, cyapa->max_abs_y, 0,
@ -801,35 +830,25 @@ static int cyapa_create_input_dev(struct cyapa *cyapa)
if (cyapa->btn_capability == CAPABILITY_LEFT_BTN_MASK)
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
/* handle pointer emulation and unused slots in core */
ret = input_mt_init_slots(input, CYAPA_MAX_MT_SLOTS,
INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED);
if (ret) {
dev_err(dev, "allocate memory for MT slots failed, %d\n", ret);
goto err_free_device;
/* Handle pointer emulation and unused slots in core */
error = input_mt_init_slots(input, CYAPA_MAX_MT_SLOTS,
INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED);
if (error) {
dev_err(dev, "failed to initialize MT slots: %d\n", error);
return error;
}
/* Register the device in input subsystem */
ret = input_register_device(input);
if (ret) {
dev_err(dev, "input device register failed, %d\n", ret);
goto err_free_device;
}
cyapa->input = input;
return 0;
err_free_device:
input_free_device(input);
cyapa->input = NULL;
return ret;
}
static int cyapa_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
int ret;
u8 adapter_func;
struct cyapa *cyapa;
struct device *dev = &client->dev;
struct cyapa *cyapa;
u8 adapter_func;
int error;
adapter_func = cyapa_check_adapter_functionality(client);
if (adapter_func == CYAPA_ADAPTER_FUNC_NONE) {
@ -837,11 +856,9 @@ static int cyapa_probe(struct i2c_client *client,
return -EIO;
}
cyapa = kzalloc(sizeof(struct cyapa), GFP_KERNEL);
if (!cyapa) {
dev_err(dev, "allocate memory for cyapa failed\n");
cyapa = devm_kzalloc(dev, sizeof(struct cyapa), GFP_KERNEL);
if (!cyapa)
return -ENOMEM;
}
cyapa->gen = CYAPA_GEN3;
cyapa->client = client;
@ -852,67 +869,61 @@ static int cyapa_probe(struct i2c_client *client,
/* i2c isn't supported, use smbus */
if (adapter_func == CYAPA_ADAPTER_FUNC_SMBUS)
cyapa->smbus = true;
cyapa->state = CYAPA_STATE_NO_DEVICE;
ret = cyapa_check_is_operational(cyapa);
if (ret) {
dev_err(dev, "device not operational, %d\n", ret);
goto err_mem_free;
error = cyapa_check_is_operational(cyapa);
if (error) {
dev_err(dev, "device not operational, %d\n", error);
return error;
}
ret = cyapa_create_input_dev(cyapa);
if (ret) {
dev_err(dev, "create input_dev instance failed, %d\n", ret);
goto err_mem_free;
/* Power down the device until we need it */
error = cyapa_set_power_mode(cyapa, PWR_MODE_OFF);
if (error) {
dev_err(dev, "failed to quiesce the device: %d\n", error);
return error;
}
ret = cyapa_set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE);
if (ret) {
dev_err(dev, "set active power failed, %d\n", ret);
goto err_unregister_device;
error = cyapa_create_input_dev(cyapa);
if (error)
return error;
error = devm_request_threaded_irq(dev, client->irq,
NULL, cyapa_irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"cyapa", cyapa);
if (error) {
dev_err(dev, "failed to request threaded irq: %d\n", error);
return error;
}
cyapa->irq = client->irq;
ret = request_threaded_irq(cyapa->irq,
NULL,
cyapa_irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"cyapa",
cyapa);
if (ret) {
dev_err(dev, "IRQ request failed: %d\n, ", ret);
goto err_unregister_device;
/* Disable IRQ until the device is opened */
disable_irq(client->irq);
/* Register the device in input subsystem */
error = input_register_device(cyapa->input);
if (error) {
dev_err(dev, "failed to register input device: %d\n", error);
return error;
}
return 0;
err_unregister_device:
input_unregister_device(cyapa->input);
err_mem_free:
kfree(cyapa);
return ret;
}
static int cyapa_remove(struct i2c_client *client)
static int __maybe_unused cyapa_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct cyapa *cyapa = i2c_get_clientdata(client);
free_irq(cyapa->irq, cyapa);
input_unregister_device(cyapa->input);
cyapa_set_power_mode(cyapa, PWR_MODE_OFF);
kfree(cyapa);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int cyapa_suspend(struct device *dev)
{
int ret;
struct input_dev *input = cyapa->input;
u8 power_mode;
struct cyapa *cyapa = dev_get_drvdata(dev);
int error;
disable_irq(cyapa->irq);
error = mutex_lock_interruptible(&input->mutex);
if (error)
return error;
disable_irq(client->irq);
/*
* Set trackpad device to idle mode if wakeup is allowed,
@ -920,31 +931,44 @@ static int cyapa_suspend(struct device *dev)
*/
power_mode = device_may_wakeup(dev) ? PWR_MODE_IDLE
: PWR_MODE_OFF;
ret = cyapa_set_power_mode(cyapa, power_mode);
if (ret < 0)
dev_err(dev, "set power mode failed, %d\n", ret);
error = cyapa_set_power_mode(cyapa, power_mode);
if (error)
dev_err(dev, "resume: set power mode to %d failed: %d\n",
power_mode, error);
if (device_may_wakeup(dev))
cyapa->irq_wake = (enable_irq_wake(cyapa->irq) == 0);
cyapa->irq_wake = (enable_irq_wake(client->irq) == 0);
mutex_unlock(&input->mutex);
return 0;
}
static int cyapa_resume(struct device *dev)
static int __maybe_unused cyapa_resume(struct device *dev)
{
int ret;
struct cyapa *cyapa = dev_get_drvdata(dev);
struct i2c_client *client = to_i2c_client(dev);
struct cyapa *cyapa = i2c_get_clientdata(client);
struct input_dev *input = cyapa->input;
u8 power_mode;
int error;
mutex_lock(&input->mutex);
if (device_may_wakeup(dev) && cyapa->irq_wake)
disable_irq_wake(cyapa->irq);
disable_irq_wake(client->irq);
ret = cyapa_set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE);
if (ret)
dev_warn(dev, "resume active power failed, %d\n", ret);
power_mode = input->users ? PWR_MODE_FULL_ACTIVE : PWR_MODE_OFF;
error = cyapa_set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE);
if (error)
dev_warn(dev, "resume: set power mode to %d failed: %d\n",
power_mode, error);
enable_irq(client->irq);
mutex_unlock(&input->mutex);
enable_irq(cyapa->irq);
return 0;
}
#endif /* CONFIG_PM_SLEEP */
static SIMPLE_DEV_PM_OPS(cyapa_pm_ops, cyapa_suspend, cyapa_resume);
@ -962,7 +986,6 @@ static struct i2c_driver cyapa_driver = {
},
.probe = cyapa_probe,
.remove = cyapa_remove,
.id_table = cyapa_id_table,
};

View File

@ -0,0 +1,86 @@
/*
* Elan I2C/SMBus Touchpad driver
*
* Copyright (c) 2013 ELAN Microelectronics Corp.
*
* Author: (Duson Lin) <dusonlin@emc.com.tw>
* Version: 1.5.5
*
* Based on cyapa driver:
* copyright (c) 2011-2012 Cypress Semiconductor, Inc.
* copyright (c) 2011-2012 Google, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* Trademarks are the property of their respective owners.
*/
#ifndef _ELAN_I2C_H
#define _ELAN_i2C_H
#include <linux/types.h>
#define ETP_ENABLE_ABS 0x0001
#define ETP_ENABLE_CALIBRATE 0x0002
#define ETP_DISABLE_CALIBRATE 0x0000
#define ETP_DISABLE_POWER 0x0001
/* IAP Firmware handling */
#define ETP_FW_NAME "elan_i2c.bin"
#define ETP_IAP_START_ADDR 0x0083
#define ETP_FW_IAP_PAGE_ERR (1 << 5)
#define ETP_FW_IAP_INTF_ERR (1 << 4)
#define ETP_FW_PAGE_SIZE 64
#define ETP_FW_PAGE_COUNT 768
#define ETP_FW_SIZE (ETP_FW_PAGE_SIZE * ETP_FW_PAGE_COUNT)
struct i2c_client;
struct completion;
enum tp_mode {
IAP_MODE = 1,
MAIN_MODE
};
struct elan_transport_ops {
int (*initialize)(struct i2c_client *client);
int (*sleep_control)(struct i2c_client *, bool sleep);
int (*power_control)(struct i2c_client *, bool enable);
int (*set_mode)(struct i2c_client *client, u8 mode);
int (*calibrate)(struct i2c_client *client);
int (*calibrate_result)(struct i2c_client *client, u8 *val);
int (*get_baseline_data)(struct i2c_client *client,
bool max_baseliune, u8 *value);
int (*get_version)(struct i2c_client *client, bool iap, u8 *version);
int (*get_sm_version)(struct i2c_client *client, u8 *version);
int (*get_checksum)(struct i2c_client *client, bool iap, u16 *csum);
int (*get_product_id)(struct i2c_client *client, u8 *id);
int (*get_max)(struct i2c_client *client,
unsigned int *max_x, unsigned int *max_y);
int (*get_resolution)(struct i2c_client *client,
u8 *hw_res_x, u8 *hw_res_y);
int (*get_num_traces)(struct i2c_client *client,
unsigned int *x_tracenum,
unsigned int *y_tracenum);
int (*iap_get_mode)(struct i2c_client *client, enum tp_mode *mode);
int (*iap_reset)(struct i2c_client *client);
int (*prepare_fw_update)(struct i2c_client *client);
int (*write_fw_block)(struct i2c_client *client,
const u8 *page, u16 checksum, int idx);
int (*finish_fw_update)(struct i2c_client *client,
struct completion *reset_done);
int (*get_report)(struct i2c_client *client, u8 *report);
};
extern const struct elan_transport_ops elan_smbus_ops, elan_i2c_ops;
#endif /* _ELAN_I2C_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,611 @@
/*
* Elan I2C/SMBus Touchpad driver - I2C interface
*
* Copyright (c) 2013 ELAN Microelectronics Corp.
*
* Author: (Duson Lin) <dusonlin@emc.com.tw>
* Version: 1.5.5
*
* Based on cyapa driver:
* copyright (c) 2011-2012 Cypress Semiconductor, Inc.
* copyright (c) 2011-2012 Google, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* Trademarks are the property of their respective owners.
*/
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/unaligned.h>
#include "elan_i2c.h"
/* Elan i2c commands */
#define ETP_I2C_RESET 0x0100
#define ETP_I2C_WAKE_UP 0x0800
#define ETP_I2C_SLEEP 0x0801
#define ETP_I2C_DESC_CMD 0x0001
#define ETP_I2C_REPORT_DESC_CMD 0x0002
#define ETP_I2C_STAND_CMD 0x0005
#define ETP_I2C_UNIQUEID_CMD 0x0101
#define ETP_I2C_FW_VERSION_CMD 0x0102
#define ETP_I2C_SM_VERSION_CMD 0x0103
#define ETP_I2C_XY_TRACENUM_CMD 0x0105
#define ETP_I2C_MAX_X_AXIS_CMD 0x0106
#define ETP_I2C_MAX_Y_AXIS_CMD 0x0107
#define ETP_I2C_RESOLUTION_CMD 0x0108
#define ETP_I2C_IAP_VERSION_CMD 0x0110
#define ETP_I2C_SET_CMD 0x0300
#define ETP_I2C_POWER_CMD 0x0307
#define ETP_I2C_FW_CHECKSUM_CMD 0x030F
#define ETP_I2C_IAP_CTRL_CMD 0x0310
#define ETP_I2C_IAP_CMD 0x0311
#define ETP_I2C_IAP_RESET_CMD 0x0314
#define ETP_I2C_IAP_CHECKSUM_CMD 0x0315
#define ETP_I2C_CALIBRATE_CMD 0x0316
#define ETP_I2C_MAX_BASELINE_CMD 0x0317
#define ETP_I2C_MIN_BASELINE_CMD 0x0318
#define ETP_I2C_REPORT_LEN 34
#define ETP_I2C_DESC_LENGTH 30
#define ETP_I2C_REPORT_DESC_LENGTH 158
#define ETP_I2C_INF_LENGTH 2
#define ETP_I2C_IAP_PASSWORD 0x1EA5
#define ETP_I2C_IAP_RESET 0xF0F0
#define ETP_I2C_MAIN_MODE_ON (1 << 9)
#define ETP_I2C_IAP_REG_L 0x01
#define ETP_I2C_IAP_REG_H 0x06
static int elan_i2c_read_block(struct i2c_client *client,
u16 reg, u8 *val, u16 len)
{
__le16 buf[] = {
cpu_to_le16(reg),
};
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = client->flags & I2C_M_TEN,
.len = sizeof(buf),
.buf = (u8 *)buf,
},
{
.addr = client->addr,
.flags = (client->flags & I2C_M_TEN) | I2C_M_RD,
.len = len,
.buf = val,
}
};
int ret;
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
return ret == ARRAY_SIZE(msgs) ? 0 : (ret < 0 ? ret : -EIO);
}
static int elan_i2c_read_cmd(struct i2c_client *client, u16 reg, u8 *val)
{
int retval;
retval = elan_i2c_read_block(client, reg, val, ETP_I2C_INF_LENGTH);
if (retval < 0) {
dev_err(&client->dev, "reading cmd (0x%04x) fail.\n", reg);
return retval;
}
return 0;
}
static int elan_i2c_write_cmd(struct i2c_client *client, u16 reg, u16 cmd)
{
__le16 buf[] = {
cpu_to_le16(reg),
cpu_to_le16(cmd),
};
struct i2c_msg msg = {
.addr = client->addr,
.flags = client->flags & I2C_M_TEN,
.len = sizeof(buf),
.buf = (u8 *)buf,
};
int ret;
ret = i2c_transfer(client->adapter, &msg, 1);
return ret == 1 ? 0 : (ret < 0 ? ret : -EIO);
}
static int elan_i2c_initialize(struct i2c_client *client)
{
struct device *dev = &client->dev;
int error;
u8 val[256];
error = elan_i2c_write_cmd(client, ETP_I2C_STAND_CMD, ETP_I2C_RESET);
if (error) {
dev_err(dev, "device reset failed: %d\n", error);
return error;
}
/* Wait for the device to reset */
msleep(100);
/* get reset acknowledgement 0000 */
error = i2c_master_recv(client, val, ETP_I2C_INF_LENGTH);
if (error < 0) {
dev_err(dev, "failed to read reset response: %d\n", error);
return error;
}
error = elan_i2c_read_block(client, ETP_I2C_DESC_CMD,
val, ETP_I2C_DESC_LENGTH);
if (error) {
dev_err(dev, "cannot get device descriptor: %d\n", error);
return error;
}
error = elan_i2c_read_block(client, ETP_I2C_REPORT_DESC_CMD,
val, ETP_I2C_REPORT_DESC_LENGTH);
if (error) {
dev_err(dev, "fetching report descriptor failed.: %d\n", error);
return error;
}
return 0;
}
static int elan_i2c_sleep_control(struct i2c_client *client, bool sleep)
{
return elan_i2c_write_cmd(client, ETP_I2C_STAND_CMD,
sleep ? ETP_I2C_SLEEP : ETP_I2C_WAKE_UP);
}
static int elan_i2c_power_control(struct i2c_client *client, bool enable)
{
u8 val[2];
u16 reg;
int error;
error = elan_i2c_read_cmd(client, ETP_I2C_POWER_CMD, val);
if (error) {
dev_err(&client->dev,
"failed to read current power state: %d\n",
error);
return error;
}
reg = le16_to_cpup((__le16 *)val);
if (enable)
reg &= ~ETP_DISABLE_POWER;
else
reg |= ETP_DISABLE_POWER;
error = elan_i2c_write_cmd(client, ETP_I2C_POWER_CMD, reg);
if (error) {
dev_err(&client->dev,
"failed to write current power state: %d\n",
error);
return error;
}
return 0;
}
static int elan_i2c_set_mode(struct i2c_client *client, u8 mode)
{
return elan_i2c_write_cmd(client, ETP_I2C_SET_CMD, mode);
}
static int elan_i2c_calibrate(struct i2c_client *client)
{
return elan_i2c_write_cmd(client, ETP_I2C_CALIBRATE_CMD, 1);
}
static int elan_i2c_calibrate_result(struct i2c_client *client, u8 *val)
{
return elan_i2c_read_block(client, ETP_I2C_CALIBRATE_CMD, val, 1);
}
static int elan_i2c_get_baseline_data(struct i2c_client *client,
bool max_baseline, u8 *value)
{
int error;
u8 val[3];
error = elan_i2c_read_cmd(client,
max_baseline ? ETP_I2C_MAX_BASELINE_CMD :
ETP_I2C_MIN_BASELINE_CMD,
val);
if (error)
return error;
*value = le16_to_cpup((__le16 *)val);
return 0;
}
static int elan_i2c_get_version(struct i2c_client *client,
bool iap, u8 *version)
{
int error;
u8 val[3];
error = elan_i2c_read_cmd(client,
iap ? ETP_I2C_IAP_VERSION_CMD :
ETP_I2C_FW_VERSION_CMD,
val);
if (error) {
dev_err(&client->dev, "failed to get %s version: %d\n",
iap ? "IAP" : "FW", error);
return error;
}
*version = val[0];
return 0;
}
static int elan_i2c_get_sm_version(struct i2c_client *client, u8 *version)
{
int error;
u8 val[3];
error = elan_i2c_read_cmd(client, ETP_I2C_SM_VERSION_CMD, val);
if (error) {
dev_err(&client->dev, "failed to get SM version: %d\n", error);
return error;
}
*version = val[0];
return 0;
}
static int elan_i2c_get_product_id(struct i2c_client *client, u8 *id)
{
int error;
u8 val[3];
error = elan_i2c_read_cmd(client, ETP_I2C_UNIQUEID_CMD, val);
if (error) {
dev_err(&client->dev, "failed to get product ID: %d\n", error);
return error;
}
*id = val[0];
return 0;
}
static int elan_i2c_get_checksum(struct i2c_client *client,
bool iap, u16 *csum)
{
int error;
u8 val[3];
error = elan_i2c_read_cmd(client,
iap ? ETP_I2C_IAP_CHECKSUM_CMD :
ETP_I2C_FW_CHECKSUM_CMD,
val);
if (error) {
dev_err(&client->dev, "failed to get %s checksum: %d\n",
iap ? "IAP" : "FW", error);
return error;
}
*csum = le16_to_cpup((__le16 *)val);
return 0;
}
static int elan_i2c_get_max(struct i2c_client *client,
unsigned int *max_x, unsigned int *max_y)
{
int error;
u8 val[3];
error = elan_i2c_read_cmd(client, ETP_I2C_MAX_X_AXIS_CMD, val);
if (error) {
dev_err(&client->dev, "failed to get X dimension: %d\n", error);
return error;
}
*max_x = le16_to_cpup((__le16 *)val) & 0x0fff;
error = elan_i2c_read_cmd(client, ETP_I2C_MAX_Y_AXIS_CMD, val);
if (error) {
dev_err(&client->dev, "failed to get Y dimension: %d\n", error);
return error;
}
*max_y = le16_to_cpup((__le16 *)val) & 0x0fff;
return 0;
}
static int elan_i2c_get_resolution(struct i2c_client *client,
u8 *hw_res_x, u8 *hw_res_y)
{
int error;
u8 val[3];
error = elan_i2c_read_cmd(client, ETP_I2C_RESOLUTION_CMD, val);
if (error) {
dev_err(&client->dev, "failed to get resolution: %d\n", error);
return error;
}
*hw_res_x = val[0];
*hw_res_y = val[1];
return 0;
}
static int elan_i2c_get_num_traces(struct i2c_client *client,
unsigned int *x_traces,
unsigned int *y_traces)
{
int error;
u8 val[3];
error = elan_i2c_read_cmd(client, ETP_I2C_XY_TRACENUM_CMD, val);
if (error) {
dev_err(&client->dev, "failed to get trace info: %d\n", error);
return error;
}
*x_traces = val[0] - 1;
*y_traces = val[1] - 1;
return 0;
}
static int elan_i2c_iap_get_mode(struct i2c_client *client, enum tp_mode *mode)
{
int error;
u16 constant;
u8 val[3];
error = elan_i2c_read_cmd(client, ETP_I2C_IAP_CTRL_CMD, val);
if (error) {
dev_err(&client->dev,
"failed to read iap control register: %d\n",
error);
return error;
}
constant = le16_to_cpup((__le16 *)val);
dev_dbg(&client->dev, "iap control reg: 0x%04x.\n", constant);
*mode = (constant & ETP_I2C_MAIN_MODE_ON) ? MAIN_MODE : IAP_MODE;
return 0;
}
static int elan_i2c_iap_reset(struct i2c_client *client)
{
int error;
error = elan_i2c_write_cmd(client, ETP_I2C_IAP_RESET_CMD,
ETP_I2C_IAP_RESET);
if (error) {
dev_err(&client->dev, "cannot reset IC: %d\n", error);
return error;
}
return 0;
}
static int elan_i2c_set_flash_key(struct i2c_client *client)
{
int error;
error = elan_i2c_write_cmd(client, ETP_I2C_IAP_CMD,
ETP_I2C_IAP_PASSWORD);
if (error) {
dev_err(&client->dev, "cannot set flash key: %d\n", error);
return error;
}
return 0;
}
static int elan_i2c_prepare_fw_update(struct i2c_client *client)
{
struct device *dev = &client->dev;
int error;
enum tp_mode mode;
u8 val[3];
u16 password;
/* Get FW in which mode (IAP_MODE/MAIN_MODE) */
error = elan_i2c_iap_get_mode(client, &mode);
if (error)
return error;
if (mode == IAP_MODE) {
/* Reset IC */
error = elan_i2c_iap_reset(client);
if (error)
return error;
msleep(30);
}
/* Set flash key*/
error = elan_i2c_set_flash_key(client);
if (error)
return error;
/* Wait for F/W IAP initialization */
msleep(mode == MAIN_MODE ? 100 : 30);
/* Check if we are in IAP mode or not */
error = elan_i2c_iap_get_mode(client, &mode);
if (error)
return error;
if (mode == MAIN_MODE) {
dev_err(dev, "wrong mode: %d\n", mode);
return -EIO;
}
/* Set flash key again */
error = elan_i2c_set_flash_key(client);
if (error)
return error;
/* Wait for F/W IAP initialization */
msleep(30);
/* read back to check we actually enabled successfully. */
error = elan_i2c_read_cmd(client, ETP_I2C_IAP_CMD, val);
if (error) {
dev_err(dev, "cannot read iap password: %d\n",
error);
return error;
}
password = le16_to_cpup((__le16 *)val);
if (password != ETP_I2C_IAP_PASSWORD) {
dev_err(dev, "wrong iap password: 0x%X\n", password);
return -EIO;
}
return 0;
}
static int elan_i2c_write_fw_block(struct i2c_client *client,
const u8 *page, u16 checksum, int idx)
{
struct device *dev = &client->dev;
u8 page_store[ETP_FW_PAGE_SIZE + 4];
u8 val[3];
u16 result;
int ret, error;
page_store[0] = ETP_I2C_IAP_REG_L;
page_store[1] = ETP_I2C_IAP_REG_H;
memcpy(&page_store[2], page, ETP_FW_PAGE_SIZE);
/* recode checksum at last two bytes */
put_unaligned_le16(checksum, &page_store[ETP_FW_PAGE_SIZE + 2]);
ret = i2c_master_send(client, page_store, sizeof(page_store));
if (ret != sizeof(page_store)) {
error = ret < 0 ? ret : -EIO;
dev_err(dev, "Failed to write page %d: %d\n", idx, error);
return error;
}
/* Wait for F/W to update one page ROM data. */
msleep(20);
error = elan_i2c_read_cmd(client, ETP_I2C_IAP_CTRL_CMD, val);
if (error) {
dev_err(dev, "Failed to read IAP write result: %d\n", error);
return error;
}
result = le16_to_cpup((__le16 *)val);
if (result & (ETP_FW_IAP_PAGE_ERR | ETP_FW_IAP_INTF_ERR)) {
dev_err(dev, "IAP reports failed write: %04hx\n",
result);
return -EIO;
}
return 0;
}
static int elan_i2c_finish_fw_update(struct i2c_client *client,
struct completion *completion)
{
struct device *dev = &client->dev;
long ret;
int error;
int len;
u8 buffer[ETP_I2C_INF_LENGTH];
reinit_completion(completion);
enable_irq(client->irq);
error = elan_i2c_write_cmd(client, ETP_I2C_STAND_CMD, ETP_I2C_RESET);
if (!error)
ret = wait_for_completion_interruptible_timeout(completion,
msecs_to_jiffies(300));
disable_irq(client->irq);
if (error) {
dev_err(dev, "device reset failed: %d\n", error);
return error;
} else if (ret == 0) {
dev_err(dev, "timeout waiting for device reset\n");
return -ETIMEDOUT;
} else if (ret < 0) {
error = ret;
dev_err(dev, "error waiting for device reset: %d\n", error);
return error;
}
len = i2c_master_recv(client, buffer, ETP_I2C_INF_LENGTH);
if (len != ETP_I2C_INF_LENGTH) {
error = len < 0 ? len : -EIO;
dev_err(dev, "failed to read INT signal: %d (%d)\n",
error, len);
return error;
}
return 0;
}
static int elan_i2c_get_report(struct i2c_client *client, u8 *report)
{
int len;
len = i2c_master_recv(client, report, ETP_I2C_REPORT_LEN);
if (len < 0) {
dev_err(&client->dev, "failed to read report data: %d\n", len);
return len;
}
if (len != ETP_I2C_REPORT_LEN) {
dev_err(&client->dev,
"wrong report length (%d vs %d expected)\n",
len, ETP_I2C_REPORT_LEN);
return -EIO;
}
return 0;
}
const struct elan_transport_ops elan_i2c_ops = {
.initialize = elan_i2c_initialize,
.sleep_control = elan_i2c_sleep_control,
.power_control = elan_i2c_power_control,
.set_mode = elan_i2c_set_mode,
.calibrate = elan_i2c_calibrate,
.calibrate_result = elan_i2c_calibrate_result,
.get_baseline_data = elan_i2c_get_baseline_data,
.get_version = elan_i2c_get_version,
.get_sm_version = elan_i2c_get_sm_version,
.get_product_id = elan_i2c_get_product_id,
.get_checksum = elan_i2c_get_checksum,
.get_max = elan_i2c_get_max,
.get_resolution = elan_i2c_get_resolution,
.get_num_traces = elan_i2c_get_num_traces,
.iap_get_mode = elan_i2c_iap_get_mode,
.iap_reset = elan_i2c_iap_reset,
.prepare_fw_update = elan_i2c_prepare_fw_update,
.write_fw_block = elan_i2c_write_fw_block,
.finish_fw_update = elan_i2c_finish_fw_update,
.get_report = elan_i2c_get_report,
};

View File

@ -0,0 +1,514 @@
/*
* Elan I2C/SMBus Touchpad driver - SMBus interface
*
* Copyright (c) 2013 ELAN Microelectronics Corp.
*
* Author: (Duson Lin) <dusonlin@emc.com.tw>
* Version: 1.5.5
*
* Based on cyapa driver:
* copyright (c) 2011-2012 Cypress Semiconductor, Inc.
* copyright (c) 2011-2012 Google, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* Trademarks are the property of their respective owners.
*/
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include "elan_i2c.h"
/* Elan SMbus commands */
#define ETP_SMBUS_IAP_CMD 0x00
#define ETP_SMBUS_ENABLE_TP 0x20
#define ETP_SMBUS_SLEEP_CMD 0x21
#define ETP_SMBUS_IAP_PASSWORD_WRITE 0x29
#define ETP_SMBUS_IAP_PASSWORD_READ 0x80
#define ETP_SMBUS_WRITE_FW_BLOCK 0x2A
#define ETP_SMBUS_IAP_RESET_CMD 0x2B
#define ETP_SMBUS_RANGE_CMD 0xA0
#define ETP_SMBUS_FW_VERSION_CMD 0xA1
#define ETP_SMBUS_XY_TRACENUM_CMD 0xA2
#define ETP_SMBUS_SM_VERSION_CMD 0xA3
#define ETP_SMBUS_UNIQUEID_CMD 0xA3
#define ETP_SMBUS_RESOLUTION_CMD 0xA4
#define ETP_SMBUS_HELLOPACKET_CMD 0xA7
#define ETP_SMBUS_PACKET_QUERY 0xA8
#define ETP_SMBUS_IAP_VERSION_CMD 0xAC
#define ETP_SMBUS_IAP_CTRL_CMD 0xAD
#define ETP_SMBUS_IAP_CHECKSUM_CMD 0xAE
#define ETP_SMBUS_FW_CHECKSUM_CMD 0xAF
#define ETP_SMBUS_MAX_BASELINE_CMD 0xC3
#define ETP_SMBUS_MIN_BASELINE_CMD 0xC4
#define ETP_SMBUS_CALIBRATE_QUERY 0xC5
#define ETP_SMBUS_REPORT_LEN 32
#define ETP_SMBUS_REPORT_OFFSET 2
#define ETP_SMBUS_HELLOPACKET_LEN 5
#define ETP_SMBUS_IAP_PASSWORD 0x1234
#define ETP_SMBUS_IAP_MODE_ON (1 << 6)
static int elan_smbus_initialize(struct i2c_client *client)
{
u8 check[ETP_SMBUS_HELLOPACKET_LEN] = { 0x55, 0x55, 0x55, 0x55, 0x55 };
u8 values[ETP_SMBUS_HELLOPACKET_LEN] = { 0, 0, 0, 0, 0 };
int len, error;
/* Get hello packet */
len = i2c_smbus_read_block_data(client,
ETP_SMBUS_HELLOPACKET_CMD, values);
if (len != ETP_SMBUS_HELLOPACKET_LEN) {
dev_err(&client->dev, "hello packet length fail: %d\n", len);
error = len < 0 ? len : -EIO;
return error;
}
/* compare hello packet */
if (memcmp(values, check, ETP_SMBUS_HELLOPACKET_LEN)) {
dev_err(&client->dev, "hello packet fail [%*px]\n",
ETP_SMBUS_HELLOPACKET_LEN, values);
return -ENXIO;
}
/* enable tp */
error = i2c_smbus_write_byte(client, ETP_SMBUS_ENABLE_TP);
if (error) {
dev_err(&client->dev, "failed to enable touchpad: %d\n", error);
return error;
}
return 0;
}
static int elan_smbus_set_mode(struct i2c_client *client, u8 mode)
{
u8 cmd[4] = { 0x00, 0x07, 0x00, mode };
return i2c_smbus_write_block_data(client, ETP_SMBUS_IAP_CMD,
sizeof(cmd), cmd);
}
static int elan_smbus_sleep_control(struct i2c_client *client, bool sleep)
{
if (sleep)
return i2c_smbus_write_byte(client, ETP_SMBUS_SLEEP_CMD);
else
return 0; /* XXX should we send ETP_SMBUS_ENABLE_TP here? */
}
static int elan_smbus_power_control(struct i2c_client *client, bool enable)
{
return 0; /* A no-op */
}
static int elan_smbus_calibrate(struct i2c_client *client)
{
u8 cmd[4] = { 0x00, 0x08, 0x00, 0x01 };
return i2c_smbus_write_block_data(client, ETP_SMBUS_IAP_CMD,
sizeof(cmd), cmd);
}
static int elan_smbus_calibrate_result(struct i2c_client *client, u8 *val)
{
int error;
error = i2c_smbus_read_block_data(client,
ETP_SMBUS_CALIBRATE_QUERY, val);
if (error < 0)
return error;
return 0;
}
static int elan_smbus_get_baseline_data(struct i2c_client *client,
bool max_baseline, u8 *value)
{
int error;
u8 val[3];
error = i2c_smbus_read_block_data(client,
max_baseline ?
ETP_SMBUS_MAX_BASELINE_CMD :
ETP_SMBUS_MIN_BASELINE_CMD,
val);
if (error < 0)
return error;
*value = be16_to_cpup((__be16 *)val);
return 0;
}
static int elan_smbus_get_version(struct i2c_client *client,
bool iap, u8 *version)
{
int error;
u8 val[3];
error = i2c_smbus_read_block_data(client,
iap ? ETP_SMBUS_IAP_VERSION_CMD :
ETP_SMBUS_FW_VERSION_CMD,
val);
if (error < 0) {
dev_err(&client->dev, "failed to get %s version: %d\n",
iap ? "IAP" : "FW", error);
return error;
}
*version = val[2];
return 0;
}
static int elan_smbus_get_sm_version(struct i2c_client *client, u8 *version)
{
int error;
u8 val[3];
error = i2c_smbus_read_block_data(client,
ETP_SMBUS_SM_VERSION_CMD, val);
if (error < 0) {
dev_err(&client->dev, "failed to get SM version: %d\n", error);
return error;
}
*version = val[0]; /* XXX Why 0 and not 2 as in IAP/FW versions? */
return 0;
}
static int elan_smbus_get_product_id(struct i2c_client *client, u8 *id)
{
int error;
u8 val[3];
error = i2c_smbus_read_block_data(client,
ETP_SMBUS_UNIQUEID_CMD, val);
if (error < 0) {
dev_err(&client->dev, "failed to get product ID: %d\n", error);
return error;
}
*id = val[1];
return 0;
}
static int elan_smbus_get_checksum(struct i2c_client *client,
bool iap, u16 *csum)
{
int error;
u8 val[3];
error = i2c_smbus_read_block_data(client,
iap ? ETP_SMBUS_FW_CHECKSUM_CMD :
ETP_SMBUS_IAP_CHECKSUM_CMD,
val);
if (error < 0) {
dev_err(&client->dev, "failed to get %s checksum: %d\n",
iap ? "IAP" : "FW", error);
return error;
}
*csum = be16_to_cpup((__be16 *)val);
return 0;
}
static int elan_smbus_get_max(struct i2c_client *client,
unsigned int *max_x, unsigned int *max_y)
{
int error;
u8 val[3];
error = i2c_smbus_read_block_data(client, ETP_SMBUS_RANGE_CMD, val);
if (error) {
dev_err(&client->dev, "failed to get dimensions: %d\n", error);
return error;
}
*max_x = (0x0f & val[0]) << 8 | val[1];
*max_y = (0xf0 & val[0]) << 4 | val[2];
return 0;
}
static int elan_smbus_get_resolution(struct i2c_client *client,
u8 *hw_res_x, u8 *hw_res_y)
{
int error;
u8 val[3];
error = i2c_smbus_read_block_data(client,
ETP_SMBUS_RESOLUTION_CMD, val);
if (error) {
dev_err(&client->dev, "failed to get resolution: %d\n", error);
return error;
}
*hw_res_x = val[1] & 0x0F;
*hw_res_y = (val[1] & 0xF0) >> 4;
return 0;
}
static int elan_smbus_get_num_traces(struct i2c_client *client,
unsigned int *x_traces,
unsigned int *y_traces)
{
int error;
u8 val[3];
error = i2c_smbus_read_block_data(client,
ETP_SMBUS_XY_TRACENUM_CMD, val);
if (error) {
dev_err(&client->dev, "failed to get trace info: %d\n", error);
return error;
}
*x_traces = val[1] - 1;
*y_traces = val[2] - 1;
return 0;
}
static int elan_smbus_iap_get_mode(struct i2c_client *client,
enum tp_mode *mode)
{
int error;
u16 constant;
u8 val[3];
error = i2c_smbus_read_block_data(client, ETP_SMBUS_IAP_CTRL_CMD, val);
if (error < 0) {
dev_err(&client->dev, "failed to read iap ctrol register: %d\n",
error);
return error;
}
constant = be16_to_cpup((__be16 *)val);
dev_dbg(&client->dev, "iap control reg: 0x%04x.\n", constant);
*mode = (constant & ETP_SMBUS_IAP_MODE_ON) ? IAP_MODE : MAIN_MODE;
return 0;
}
static int elan_smbus_iap_reset(struct i2c_client *client)
{
int error;
error = i2c_smbus_write_byte(client, ETP_SMBUS_IAP_RESET_CMD);
if (error) {
dev_err(&client->dev, "cannot reset IC: %d\n", error);
return error;
}
return 0;
}
static int elan_smbus_set_flash_key(struct i2c_client *client)
{
int error;
u8 cmd[4] = { 0x00, 0x0B, 0x00, 0x5A };
error = i2c_smbus_write_block_data(client, ETP_SMBUS_IAP_CMD,
sizeof(cmd), cmd);
if (error) {
dev_err(&client->dev, "cannot set flash key: %d\n", error);
return error;
}
return 0;
}
static int elan_smbus_prepare_fw_update(struct i2c_client *client)
{
struct device *dev = &client->dev;
int len;
int error;
enum tp_mode mode;
u8 val[3];
u8 cmd[4] = {0x0F, 0x78, 0x00, 0x06};
u16 password;
/* Get FW in which mode (IAP_MODE/MAIN_MODE) */
error = elan_smbus_iap_get_mode(client, &mode);
if (error)
return error;
if (mode == MAIN_MODE) {
/* set flash key */
error = elan_smbus_set_flash_key(client);
if (error)
return error;
/* write iap password */
if (i2c_smbus_write_byte(client,
ETP_SMBUS_IAP_PASSWORD_WRITE) < 0) {
dev_err(dev, "cannot write iap password\n");
return -EIO;
}
error = i2c_smbus_write_block_data(client, ETP_SMBUS_IAP_CMD,
sizeof(cmd), cmd);
if (error) {
dev_err(dev, "failed to write iap password: %d\n",
error);
return error;
}
/*
* Read back password to make sure we enabled flash
* successfully.
*/
len = i2c_smbus_read_block_data(client,
ETP_SMBUS_IAP_PASSWORD_READ,
val);
if (len < sizeof(u16)) {
error = len < 0 ? len : -EIO;
dev_err(dev, "failed to read iap password: %d\n",
error);
return error;
}
password = be16_to_cpup((__be16 *)val);
if (password != ETP_SMBUS_IAP_PASSWORD) {
dev_err(dev, "wrong iap password = 0x%X\n", password);
return -EIO;
}
/* Wait 30ms for MAIN_MODE change to IAP_MODE */
msleep(30);
}
error = elan_smbus_set_flash_key(client);
if (error)
return error;
/* Reset IC */
error = elan_smbus_iap_reset(client);
if (error)
return error;
return 0;
}
static int elan_smbus_write_fw_block(struct i2c_client *client,
const u8 *page, u16 checksum, int idx)
{
struct device *dev = &client->dev;
int error;
u16 result;
u8 val[3];
/*
* Due to the limitation of smbus protocol limiting
* transfer to 32 bytes at a time, we must split block
* in 2 transfers.
*/
error = i2c_smbus_write_block_data(client,
ETP_SMBUS_WRITE_FW_BLOCK,
ETP_FW_PAGE_SIZE / 2,
page);
if (error) {
dev_err(dev, "Failed to write page %d (part %d): %d\n",
idx, 1, error);
return error;
}
error = i2c_smbus_write_block_data(client,
ETP_SMBUS_WRITE_FW_BLOCK,
ETP_FW_PAGE_SIZE / 2,
page + ETP_FW_PAGE_SIZE / 2);
if (error) {
dev_err(dev, "Failed to write page %d (part %d): %d\n",
idx, 2, error);
return error;
}
/* Wait for F/W to update one page ROM data. */
usleep_range(8000, 10000);
error = i2c_smbus_read_block_data(client,
ETP_SMBUS_IAP_CTRL_CMD, val);
if (error < 0) {
dev_err(dev, "Failed to read IAP write result: %d\n",
error);
return error;
}
result = be16_to_cpup((__be16 *)val);
if (result & (ETP_FW_IAP_PAGE_ERR | ETP_FW_IAP_INTF_ERR)) {
dev_err(dev, "IAP reports failed write: %04hx\n",
result);
return -EIO;
}
return 0;
}
static int elan_smbus_get_report(struct i2c_client *client, u8 *report)
{
int len;
len = i2c_smbus_read_block_data(client,
ETP_SMBUS_PACKET_QUERY,
&report[ETP_SMBUS_REPORT_OFFSET]);
if (len < 0) {
dev_err(&client->dev, "failed to read report data: %d\n", len);
return len;
}
if (len != ETP_SMBUS_REPORT_LEN) {
dev_err(&client->dev,
"wrong report length (%d vs %d expected)\n",
len, ETP_SMBUS_REPORT_LEN);
return -EIO;
}
return 0;
}
static int elan_smbus_finish_fw_update(struct i2c_client *client,
struct completion *fw_completion)
{
/* No special handling unlike I2C transport */
return 0;
}
const struct elan_transport_ops elan_smbus_ops = {
.initialize = elan_smbus_initialize,
.sleep_control = elan_smbus_sleep_control,
.power_control = elan_smbus_power_control,
.set_mode = elan_smbus_set_mode,
.calibrate = elan_smbus_calibrate,
.calibrate_result = elan_smbus_calibrate_result,
.get_baseline_data = elan_smbus_get_baseline_data,
.get_version = elan_smbus_get_version,
.get_sm_version = elan_smbus_get_sm_version,
.get_product_id = elan_smbus_get_product_id,
.get_checksum = elan_smbus_get_checksum,
.get_max = elan_smbus_get_max,
.get_resolution = elan_smbus_get_resolution,
.get_num_traces = elan_smbus_get_num_traces,
.iap_get_mode = elan_smbus_iap_get_mode,
.iap_reset = elan_smbus_iap_reset,
.prepare_fw_update = elan_smbus_prepare_fw_update,
.write_fw_block = elan_smbus_write_fw_block,
.finish_fw_update = elan_smbus_finish_fw_update,
.get_report = elan_smbus_get_report,
};

View File

@ -16,14 +16,14 @@ void lifebook_module_init(void);
int lifebook_detect(struct psmouse *psmouse, bool set_properties);
int lifebook_init(struct psmouse *psmouse);
#else
inline void lifebook_module_init(void)
static inline void lifebook_module_init(void)
{
}
inline int lifebook_detect(struct psmouse *psmouse, bool set_properties)
static inline int lifebook_detect(struct psmouse *psmouse, bool set_properties)
{
return -ENOSYS;
}
inline int lifebook_init(struct psmouse *psmouse)
static inline int lifebook_init(struct psmouse *psmouse)
{
return -ENOSYS;
}

View File

@ -318,8 +318,7 @@ static int navpoint_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int navpoint_suspend(struct device *dev)
static int __maybe_unused navpoint_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct navpoint *navpoint = platform_get_drvdata(pdev);
@ -333,7 +332,7 @@ static int navpoint_suspend(struct device *dev)
return 0;
}
static int navpoint_resume(struct device *dev)
static int __maybe_unused navpoint_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct navpoint *navpoint = platform_get_drvdata(pdev);
@ -346,7 +345,6 @@ static int navpoint_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(navpoint_pm_ops, navpoint_suspend, navpoint_resume);

View File

@ -614,8 +614,7 @@ static int synaptics_i2c_remove(struct i2c_client *client)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int synaptics_i2c_suspend(struct device *dev)
static int __maybe_unused synaptics_i2c_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct synaptics_i2c *touch = i2c_get_clientdata(client);
@ -628,7 +627,7 @@ static int synaptics_i2c_suspend(struct device *dev)
return 0;
}
static int synaptics_i2c_resume(struct device *dev)
static int __maybe_unused synaptics_i2c_resume(struct device *dev)
{
int ret;
struct i2c_client *client = to_i2c_client(dev);
@ -643,7 +642,6 @@ static int synaptics_i2c_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(synaptics_i2c_pm, synaptics_i2c_suspend,
synaptics_i2c_resume);

View File

@ -24,9 +24,7 @@
struct ps2if {
struct serio *io;
struct resource *iomem_res;
void __iomem *base;
unsigned irq;
};
/*
@ -83,16 +81,34 @@ static void altera_ps2_close(struct serio *io)
static int altera_ps2_probe(struct platform_device *pdev)
{
struct ps2if *ps2if;
struct resource *res;
struct serio *serio;
int error, irq;
ps2if = kzalloc(sizeof(struct ps2if), GFP_KERNEL);
serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!ps2if || !serio) {
error = -ENOMEM;
goto err_free_mem;
ps2if = devm_kzalloc(&pdev->dev, sizeof(struct ps2if), GFP_KERNEL);
if (!ps2if)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ps2if->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ps2if->base))
return PTR_ERR(ps2if->base);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return -ENXIO;
error = devm_request_irq(&pdev->dev, irq, altera_ps2_rxint, 0,
pdev->name, ps2if);
if (error) {
dev_err(&pdev->dev, "could not request IRQ %d\n", irq);
return error;
}
serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!serio)
return -ENOMEM;
serio->id.type = SERIO_8042;
serio->write = altera_ps2_write;
serio->open = altera_ps2_open;
@ -103,56 +119,12 @@ static int altera_ps2_probe(struct platform_device *pdev)
serio->dev.parent = &pdev->dev;
ps2if->io = serio;
ps2if->iomem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (ps2if->iomem_res == NULL) {
error = -ENOENT;
goto err_free_mem;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
error = -ENXIO;
goto err_free_mem;
}
ps2if->irq = irq;
if (!request_mem_region(ps2if->iomem_res->start,
resource_size(ps2if->iomem_res), pdev->name)) {
error = -EBUSY;
goto err_free_mem;
}
ps2if->base = ioremap(ps2if->iomem_res->start,
resource_size(ps2if->iomem_res));
if (!ps2if->base) {
error = -ENOMEM;
goto err_free_res;
}
error = request_irq(ps2if->irq, altera_ps2_rxint, 0, pdev->name, ps2if);
if (error) {
dev_err(&pdev->dev, "could not allocate IRQ %d: %d\n",
ps2if->irq, error);
goto err_unmap;
}
dev_info(&pdev->dev, "base %p, irq %d\n", ps2if->base, ps2if->irq);
dev_info(&pdev->dev, "base %p, irq %d\n", ps2if->base, irq);
serio_register_port(ps2if->io);
platform_set_drvdata(pdev, ps2if);
return 0;
err_unmap:
iounmap(ps2if->base);
err_free_res:
release_mem_region(ps2if->iomem_res->start,
resource_size(ps2if->iomem_res));
err_free_mem:
kfree(ps2if);
kfree(serio);
return error;
}
/*
@ -163,11 +135,6 @@ static int altera_ps2_remove(struct platform_device *pdev)
struct ps2if *ps2if = platform_get_drvdata(pdev);
serio_unregister_port(ps2if->io);
free_irq(ps2if->irq, ps2if);
iounmap(ps2if->base);
release_mem_region(ps2if->iomem_res->start,
resource_size(ps2if->iomem_res));
kfree(ps2if);
return 0;
}

View File

@ -578,6 +578,16 @@ static const struct dmi_system_id __initconst i8042_dmi_nopnp_table[] = {
DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
},
},
{
/*
* Intel NUC D54250WYK - does not have i8042 controller but
* declares PS/2 devices in DSDT.
*/
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "D54250WYK"),
DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
},
},
{
/* MSI Wind U-100 */
.matches = {

View File

@ -514,7 +514,7 @@ static void serio_release_port(struct device *dev)
*/
static void serio_init_port(struct serio *serio)
{
static atomic_t serio_no = ATOMIC_INIT(0);
static atomic_t serio_no = ATOMIC_INIT(-1);
__module_get(THIS_MODULE);
@ -525,7 +525,7 @@ static void serio_init_port(struct serio *serio)
mutex_init(&serio->drv_mutex);
device_initialize(&serio->dev);
dev_set_name(&serio->dev, "serio%lu",
(unsigned long)atomic_inc_return(&serio_no) - 1);
(unsigned long)atomic_inc_return(&serio_no));
serio->dev.bus = &serio_bus;
serio->dev.release = serio_release_port;
serio->dev.groups = serio_device_attr_groups;

View File

@ -292,7 +292,7 @@ static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
{
static atomic_t serio_raw_no = ATOMIC_INIT(0);
static atomic_t serio_raw_no = ATOMIC_INIT(-1);
struct serio_raw *serio_raw;
int err;
@ -303,7 +303,7 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
}
snprintf(serio_raw->name, sizeof(serio_raw->name),
"serio_raw%ld", (long)atomic_inc_return(&serio_raw_no) - 1);
"serio_raw%ld", (long)atomic_inc_return(&serio_raw_no));
kref_init(&serio_raw->kref);
INIT_LIST_HEAD(&serio_raw->client_list);
init_waitqueue_head(&serio_raw->wait);

View File

@ -295,6 +295,19 @@ config TOUCHSCREEN_FUJITSU
To compile this driver as a module, choose M here: the
module will be called fujitsu-ts.
config TOUCHSCREEN_GOODIX
tristate "Goodix I2C touchscreen"
depends on I2C && ACPI
help
Say Y here if you have the Goodix touchscreen (such as one
installed in Onda v975w tablets) connected to your
system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called goodix.
config TOUCHSCREEN_ILI210X
tristate "Ilitek ILI210X based touchscreen"
depends on I2C
@ -334,6 +347,18 @@ config TOUCHSCREEN_GUNZE
To compile this driver as a module, choose M here: the
module will be called gunze.
config TOUCHSCREEN_ELAN
tristate "Elan eKTH I2C touchscreen"
depends on I2C
help
Say Y here if you have an Elan eKTH I2C touchscreen
connected to your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called elants_i2c.
config TOUCHSCREEN_ELO
tristate "Elo serial touchscreens"
select SERIO

View File

@ -31,9 +31,11 @@ obj-$(CONFIG_TOUCHSCREEN_EDT_FT5X06) += edt-ft5x06.o
obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o
obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
obj-$(CONFIG_TOUCHSCREEN_ELAN) += elants_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o

View File

@ -820,8 +820,7 @@ static int ad7877_remove(struct spi_device *spi)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int ad7877_suspend(struct device *dev)
static int __maybe_unused ad7877_suspend(struct device *dev)
{
struct ad7877 *ts = dev_get_drvdata(dev);
@ -830,7 +829,7 @@ static int ad7877_suspend(struct device *dev)
return 0;
}
static int ad7877_resume(struct device *dev)
static int __maybe_unused ad7877_resume(struct device *dev)
{
struct ad7877 *ts = dev_get_drvdata(dev);
@ -838,7 +837,6 @@ static int ad7877_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(ad7877_pm, ad7877_suspend, ad7877_resume);

View File

@ -284,8 +284,7 @@ static void ad7879_close(struct input_dev* input)
__ad7879_disable(ts);
}
#ifdef CONFIG_PM_SLEEP
static int ad7879_suspend(struct device *dev)
static int __maybe_unused ad7879_suspend(struct device *dev)
{
struct ad7879 *ts = dev_get_drvdata(dev);
@ -301,7 +300,7 @@ static int ad7879_suspend(struct device *dev)
return 0;
}
static int ad7879_resume(struct device *dev)
static int __maybe_unused ad7879_resume(struct device *dev)
{
struct ad7879 *ts = dev_get_drvdata(dev);
@ -316,7 +315,6 @@ static int ad7879_resume(struct device *dev)
return 0;
}
#endif
SIMPLE_DEV_PM_OPS(ad7879_pm_ops, ad7879_suspend, ad7879_resume);
EXPORT_SYMBOL(ad7879_pm_ops);

View File

@ -883,8 +883,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle)
return IRQ_HANDLED;
}
#ifdef CONFIG_PM_SLEEP
static int ads7846_suspend(struct device *dev)
static int __maybe_unused ads7846_suspend(struct device *dev)
{
struct ads7846 *ts = dev_get_drvdata(dev);
@ -906,7 +905,7 @@ static int ads7846_suspend(struct device *dev)
return 0;
}
static int ads7846_resume(struct device *dev)
static int __maybe_unused ads7846_resume(struct device *dev)
{
struct ads7846 *ts = dev_get_drvdata(dev);
@ -927,7 +926,6 @@ static int ads7846_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume);

View File

@ -2244,8 +2244,7 @@ static int mxt_remove(struct i2c_client *client)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int mxt_suspend(struct device *dev)
static int __maybe_unused mxt_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct mxt_data *data = i2c_get_clientdata(client);
@ -2261,7 +2260,7 @@ static int mxt_suspend(struct device *dev)
return 0;
}
static int mxt_resume(struct device *dev)
static int __maybe_unused mxt_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct mxt_data *data = i2c_get_clientdata(client);
@ -2276,7 +2275,6 @@ static int mxt_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume);

View File

@ -417,8 +417,7 @@ static void auo_pixcir_input_close(struct input_dev *dev)
return;
}
#ifdef CONFIG_PM_SLEEP
static int auo_pixcir_suspend(struct device *dev)
static int __maybe_unused auo_pixcir_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct auo_pixcir_ts *ts = i2c_get_clientdata(client);
@ -450,7 +449,7 @@ unlock:
return ret;
}
static int auo_pixcir_resume(struct device *dev)
static int __maybe_unused auo_pixcir_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct auo_pixcir_ts *ts = i2c_get_clientdata(client);
@ -479,7 +478,6 @@ unlock:
return ret;
}
#endif
static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops,
auo_pixcir_suspend, auo_pixcir_resume);

View File

@ -291,8 +291,7 @@ err_free_mem:
return err;
}
#ifdef CONFIG_PM_SLEEP
static int cy8ctmg110_suspend(struct device *dev)
static int __maybe_unused cy8ctmg110_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct cy8ctmg110 *ts = i2c_get_clientdata(client);
@ -306,7 +305,7 @@ static int cy8ctmg110_suspend(struct device *dev)
return 0;
}
static int cy8ctmg110_resume(struct device *dev)
static int __maybe_unused cy8ctmg110_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct cy8ctmg110 *ts = i2c_get_clientdata(client);
@ -319,7 +318,6 @@ static int cy8ctmg110_resume(struct device *dev)
}
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume);

View File

@ -472,8 +472,7 @@ static int cyttsp_disable(struct cyttsp *ts)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int cyttsp_suspend(struct device *dev)
static int __maybe_unused cyttsp_suspend(struct device *dev)
{
struct cyttsp *ts = dev_get_drvdata(dev);
int retval = 0;
@ -491,7 +490,7 @@ static int cyttsp_suspend(struct device *dev)
return retval;
}
static int cyttsp_resume(struct device *dev)
static int __maybe_unused cyttsp_resume(struct device *dev)
{
struct cyttsp *ts = dev_get_drvdata(dev);
@ -507,8 +506,6 @@ static int cyttsp_resume(struct device *dev)
return 0;
}
#endif
SIMPLE_DEV_PM_OPS(cyttsp_pm_ops, cyttsp_suspend, cyttsp_resume);
EXPORT_SYMBOL_GPL(cyttsp_pm_ops);

View File

@ -1092,8 +1092,7 @@ static int edt_ft5x06_ts_remove(struct i2c_client *client)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int edt_ft5x06_ts_suspend(struct device *dev)
static int __maybe_unused edt_ft5x06_ts_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@ -1103,7 +1102,7 @@ static int edt_ft5x06_ts_suspend(struct device *dev)
return 0;
}
static int edt_ft5x06_ts_resume(struct device *dev)
static int __maybe_unused edt_ft5x06_ts_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@ -1112,7 +1111,6 @@ static int edt_ft5x06_ts_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops,
edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume);

View File

@ -264,8 +264,7 @@ static int eeti_ts_remove(struct i2c_client *client)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int eeti_ts_suspend(struct device *dev)
static int __maybe_unused eeti_ts_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct eeti_ts_priv *priv = i2c_get_clientdata(client);
@ -284,7 +283,7 @@ static int eeti_ts_suspend(struct device *dev)
return 0;
}
static int eeti_ts_resume(struct device *dev)
static int __maybe_unused eeti_ts_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct eeti_ts_priv *priv = i2c_get_clientdata(client);
@ -302,7 +301,6 @@ static int eeti_ts_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(eeti_ts_pm, eeti_ts_suspend, eeti_ts_resume);

View File

@ -239,8 +239,7 @@ static const struct i2c_device_id egalax_ts_id[] = {
};
MODULE_DEVICE_TABLE(i2c, egalax_ts_id);
#ifdef CONFIG_PM_SLEEP
static int egalax_ts_suspend(struct device *dev)
static int __maybe_unused egalax_ts_suspend(struct device *dev)
{
static const u8 suspend_cmd[MAX_I2C_DATA_LEN] = {
0x3, 0x6, 0xa, 0x3, 0x36, 0x3f, 0x2, 0, 0, 0
@ -252,13 +251,12 @@ static int egalax_ts_suspend(struct device *dev)
return ret > 0 ? 0 : ret;
}
static int egalax_ts_resume(struct device *dev)
static int __maybe_unused egalax_ts_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
return egalax_wake_up_device(client);
}
#endif
static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,395 @@
/*
* Driver for Goodix Touchscreens
*
* Copyright (c) 2014 Red Hat Inc.
*
* This code is based on gt9xx.c authored by andrew@goodix.com:
*
* 2010 - 2012 Goodix Technology.
*/
/*
* 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 of the License.
*/
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
struct goodix_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
int abs_x_max;
int abs_y_max;
unsigned int max_touch_num;
unsigned int int_trigger_type;
};
#define GOODIX_MAX_HEIGHT 4096
#define GOODIX_MAX_WIDTH 4096
#define GOODIX_INT_TRIGGER 1
#define GOODIX_CONTACT_SIZE 8
#define GOODIX_MAX_CONTACTS 10
#define GOODIX_CONFIG_MAX_LENGTH 240
/* Register defines */
#define GOODIX_READ_COOR_ADDR 0x814E
#define GOODIX_REG_CONFIG_DATA 0x8047
#define GOODIX_REG_VERSION 0x8140
#define RESOLUTION_LOC 1
#define TRIGGER_LOC 6
static const unsigned long goodix_irq_flags[] = {
IRQ_TYPE_EDGE_RISING,
IRQ_TYPE_EDGE_FALLING,
IRQ_TYPE_LEVEL_LOW,
IRQ_TYPE_LEVEL_HIGH,
};
/**
* goodix_i2c_read - read data from a register of the i2c slave device.
*
* @client: i2c device.
* @reg: the register to read from.
* @buf: raw write data buffer.
* @len: length of the buffer to write
*/
static int goodix_i2c_read(struct i2c_client *client,
u16 reg, u8 *buf, int len)
{
struct i2c_msg msgs[2];
u16 wbuf = cpu_to_be16(reg);
int ret;
msgs[0].flags = 0;
msgs[0].addr = client->addr;
msgs[0].len = 2;
msgs[0].buf = (u8 *) &wbuf;
msgs[1].flags = I2C_M_RD;
msgs[1].addr = client->addr;
msgs[1].len = len;
msgs[1].buf = buf;
ret = i2c_transfer(client->adapter, msgs, 2);
return ret < 0 ? ret : (ret != ARRAY_SIZE(msgs) ? -EIO : 0);
}
static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data)
{
int touch_num;
int error;
error = goodix_i2c_read(ts->client, GOODIX_READ_COOR_ADDR, data,
GOODIX_CONTACT_SIZE + 1);
if (error) {
dev_err(&ts->client->dev, "I2C transfer error: %d\n", error);
return error;
}
touch_num = data[0] & 0x0f;
if (touch_num > GOODIX_MAX_CONTACTS)
return -EPROTO;
if (touch_num > 1) {
data += 1 + GOODIX_CONTACT_SIZE;
error = goodix_i2c_read(ts->client,
GOODIX_READ_COOR_ADDR +
1 + GOODIX_CONTACT_SIZE,
data,
GOODIX_CONTACT_SIZE * (touch_num - 1));
if (error)
return error;
}
return touch_num;
}
static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data)
{
int id = coor_data[0] & 0x0F;
int input_x = get_unaligned_le16(&coor_data[1]);
int input_y = get_unaligned_le16(&coor_data[3]);
int input_w = get_unaligned_le16(&coor_data[5]);
input_mt_slot(ts->input_dev, id);
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y);
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w);
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w);
}
/**
* goodix_process_events - Process incoming events
*
* @ts: our goodix_ts_data pointer
*
* Called when the IRQ is triggered. Read the current device state, and push
* the input events to the user space.
*/
static void goodix_process_events(struct goodix_ts_data *ts)
{
u8 point_data[1 + GOODIX_CONTACT_SIZE * GOODIX_MAX_CONTACTS];
int touch_num;
int i;
touch_num = goodix_ts_read_input_report(ts, point_data);
if (touch_num < 0)
return;
for (i = 0; i < touch_num; i++)
goodix_ts_report_touch(ts,
&point_data[1 + GOODIX_CONTACT_SIZE * i]);
input_mt_sync_frame(ts->input_dev);
input_sync(ts->input_dev);
}
/**
* goodix_ts_irq_handler - The IRQ handler
*
* @irq: interrupt number.
* @dev_id: private data pointer.
*/
static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
{
static const u8 end_cmd[] = {
GOODIX_READ_COOR_ADDR >> 8,
GOODIX_READ_COOR_ADDR & 0xff,
0
};
struct goodix_ts_data *ts = dev_id;
goodix_process_events(ts);
if (i2c_master_send(ts->client, end_cmd, sizeof(end_cmd)) < 0)
dev_err(&ts->client->dev, "I2C write end_cmd error\n");
return IRQ_HANDLED;
}
/**
* goodix_read_config - Read the embedded configuration of the panel
*
* @ts: our goodix_ts_data pointer
*
* Must be called during probe
*/
static void goodix_read_config(struct goodix_ts_data *ts)
{
u8 config[GOODIX_CONFIG_MAX_LENGTH];
int error;
error = goodix_i2c_read(ts->client, GOODIX_REG_CONFIG_DATA,
config,
GOODIX_CONFIG_MAX_LENGTH);
if (error) {
dev_warn(&ts->client->dev,
"Error reading config (%d), using defaults\n",
error);
ts->abs_x_max = GOODIX_MAX_WIDTH;
ts->abs_y_max = GOODIX_MAX_HEIGHT;
ts->int_trigger_type = GOODIX_INT_TRIGGER;
return;
}
ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]);
ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]);
ts->int_trigger_type = (config[TRIGGER_LOC]) & 0x03;
if (!ts->abs_x_max || !ts->abs_y_max) {
dev_err(&ts->client->dev,
"Invalid config, using defaults\n");
ts->abs_x_max = GOODIX_MAX_WIDTH;
ts->abs_y_max = GOODIX_MAX_HEIGHT;
}
}
/**
* goodix_read_version - Read goodix touchscreen version
*
* @client: the i2c client
* @version: output buffer containing the version on success
*/
static int goodix_read_version(struct i2c_client *client, u16 *version)
{
int error;
u8 buf[6];
error = goodix_i2c_read(client, GOODIX_REG_VERSION, buf, sizeof(buf));
if (error) {
dev_err(&client->dev, "read version failed: %d\n", error);
return error;
}
if (version)
*version = get_unaligned_le16(&buf[4]);
dev_info(&client->dev, "IC VERSION: %6ph\n", buf);
return 0;
}
/**
* goodix_i2c_test - I2C test function to check if the device answers.
*
* @client: the i2c client
*/
static int goodix_i2c_test(struct i2c_client *client)
{
int retry = 0;
int error;
u8 test;
while (retry++ < 2) {
error = goodix_i2c_read(client, GOODIX_REG_CONFIG_DATA,
&test, 1);
if (!error)
return 0;
dev_err(&client->dev, "i2c test failed attempt %d: %d\n",
retry, error);
msleep(20);
}
return error;
}
/**
* goodix_request_input_dev - Allocate, populate and register the input device
*
* @ts: our goodix_ts_data pointer
*
* Must be called during probe
*/
static int goodix_request_input_dev(struct goodix_ts_data *ts)
{
int error;
ts->input_dev = devm_input_allocate_device(&ts->client->dev);
if (!ts->input_dev) {
dev_err(&ts->client->dev, "Failed to allocate input device.");
return -ENOMEM;
}
ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) |
BIT_MASK(EV_KEY) |
BIT_MASK(EV_ABS);
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0,
ts->abs_x_max, 0, 0);
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0,
ts->abs_y_max, 0, 0);
input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
input_mt_init_slots(ts->input_dev, GOODIX_MAX_CONTACTS,
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
ts->input_dev->name = "Goodix Capacitive TouchScreen";
ts->input_dev->phys = "input/ts";
ts->input_dev->id.bustype = BUS_I2C;
ts->input_dev->id.vendor = 0x0416;
ts->input_dev->id.product = 0x1001;
ts->input_dev->id.version = 10427;
error = input_register_device(ts->input_dev);
if (error) {
dev_err(&ts->client->dev,
"Failed to register input device: %d", error);
return error;
}
return 0;
}
static int goodix_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct goodix_ts_data *ts;
unsigned long irq_flags;
int error;
u16 version_info;
dev_dbg(&client->dev, "I2C Address: 0x%02x\n", client->addr);
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
dev_err(&client->dev, "I2C check functionality failed.\n");
return -ENXIO;
}
ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
if (!ts)
return -ENOMEM;
ts->client = client;
i2c_set_clientdata(client, ts);
error = goodix_i2c_test(client);
if (error) {
dev_err(&client->dev, "I2C communication failure: %d\n", error);
return error;
}
error = goodix_read_version(client, &version_info);
if (error) {
dev_err(&client->dev, "Read version failed.\n");
return error;
}
goodix_read_config(ts);
error = goodix_request_input_dev(ts);
if (error)
return error;
irq_flags = goodix_irq_flags[ts->int_trigger_type] | IRQF_ONESHOT;
error = devm_request_threaded_irq(&ts->client->dev, client->irq,
NULL, goodix_ts_irq_handler,
irq_flags, client->name, ts);
if (error) {
dev_err(&client->dev, "request IRQ failed: %d\n", error);
return error;
}
return 0;
}
static const struct i2c_device_id goodix_ts_id[] = {
{ "GDIX1001:00", 0 },
{ }
};
static const struct acpi_device_id goodix_acpi_match[] = {
{ "GDIX1001", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, goodix_acpi_match);
static struct i2c_driver goodix_ts_driver = {
.probe = goodix_ts_probe,
.id_table = goodix_ts_id,
.driver = {
.name = "Goodix-TS",
.owner = THIS_MODULE,
.acpi_match_table = goodix_acpi_match,
},
};
module_i2c_driver(goodix_ts_driver);
MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
MODULE_DESCRIPTION("Goodix touchscreen driver");
MODULE_LICENSE("GPL v2");

View File

@ -311,8 +311,7 @@ static int ili210x_i2c_remove(struct i2c_client *client)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int ili210x_i2c_suspend(struct device *dev)
static int __maybe_unused ili210x_i2c_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@ -322,7 +321,7 @@ static int ili210x_i2c_suspend(struct device *dev)
return 0;
}
static int ili210x_i2c_resume(struct device *dev)
static int __maybe_unused ili210x_i2c_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@ -331,7 +330,6 @@ static int ili210x_i2c_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm,
ili210x_i2c_suspend, ili210x_i2c_resume);

View File

@ -122,8 +122,7 @@ static int micro_ts_probe(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int micro_ts_suspend(struct device *dev)
static int __maybe_unused micro_ts_suspend(struct device *dev)
{
struct touchscreen_data *ts = dev_get_drvdata(dev);
@ -132,7 +131,7 @@ static int micro_ts_suspend(struct device *dev)
return 0;
}
static int micro_ts_resume(struct device *dev)
static int __maybe_unused micro_ts_resume(struct device *dev)
{
struct touchscreen_data *ts = dev_get_drvdata(dev);
struct input_dev *input = ts->input;
@ -146,7 +145,6 @@ static int micro_ts_resume(struct device *dev)
return 0;
}
#endif
static const struct dev_pm_ops micro_ts_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(micro_ts_suspend, micro_ts_resume)

View File

@ -515,8 +515,7 @@ static int mms114_probe(struct i2c_client *client,
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int mms114_suspend(struct device *dev)
static int __maybe_unused mms114_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct mms114_data *data = i2c_get_clientdata(client);
@ -540,7 +539,7 @@ static int mms114_suspend(struct device *dev)
return 0;
}
static int mms114_resume(struct device *dev)
static int __maybe_unused mms114_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct mms114_data *data = i2c_get_clientdata(client);
@ -559,7 +558,6 @@ static int mms114_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(mms114_pm_ops, mms114_suspend, mms114_resume);

View File

@ -347,8 +347,7 @@ static void pixcir_input_close(struct input_dev *dev)
pixcir_stop(ts);
}
#ifdef CONFIG_PM_SLEEP
static int pixcir_i2c_ts_suspend(struct device *dev)
static int __maybe_unused pixcir_i2c_ts_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
@ -377,7 +376,7 @@ unlock:
return ret;
}
static int pixcir_i2c_ts_resume(struct device *dev)
static int __maybe_unused pixcir_i2c_ts_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
@ -405,7 +404,6 @@ unlock:
return ret;
}
#endif
static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);

View File

@ -243,8 +243,7 @@ static int st1232_ts_remove(struct i2c_client *client)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int st1232_ts_suspend(struct device *dev)
static int __maybe_unused st1232_ts_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct st1232_ts_data *ts = i2c_get_clientdata(client);
@ -259,7 +258,7 @@ static int st1232_ts_suspend(struct device *dev)
return 0;
}
static int st1232_ts_resume(struct device *dev)
static int __maybe_unused st1232_ts_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct st1232_ts_data *ts = i2c_get_clientdata(client);
@ -274,8 +273,6 @@ static int st1232_ts_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(st1232_ts_pm_ops,
st1232_ts_suspend, st1232_ts_resume);

View File

@ -773,8 +773,7 @@ static int tsc2005_remove(struct spi_device *spi)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int tsc2005_suspend(struct device *dev)
static int __maybe_unused tsc2005_suspend(struct device *dev)
{
struct spi_device *spi = to_spi_device(dev);
struct tsc2005 *ts = spi_get_drvdata(spi);
@ -791,7 +790,7 @@ static int tsc2005_suspend(struct device *dev)
return 0;
}
static int tsc2005_resume(struct device *dev)
static int __maybe_unused tsc2005_resume(struct device *dev)
{
struct spi_device *spi = to_spi_device(dev);
struct tsc2005 *ts = spi_get_drvdata(spi);
@ -807,7 +806,6 @@ static int tsc2005_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(tsc2005_pm_ops, tsc2005_suspend, tsc2005_resume);

View File

@ -406,8 +406,7 @@ static int ucb1400_ts_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int ucb1400_ts_suspend(struct device *dev)
static int __maybe_unused ucb1400_ts_suspend(struct device *dev)
{
struct ucb1400_ts *ucb = dev_get_platdata(dev);
struct input_dev *idev = ucb->ts_idev;
@ -421,7 +420,7 @@ static int ucb1400_ts_suspend(struct device *dev)
return 0;
}
static int ucb1400_ts_resume(struct device *dev)
static int __maybe_unused ucb1400_ts_resume(struct device *dev)
{
struct ucb1400_ts *ucb = dev_get_platdata(dev);
struct input_dev *idev = ucb->ts_idev;
@ -434,7 +433,6 @@ static int ucb1400_ts_resume(struct device *dev)
mutex_unlock(&idev->mutex);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(ucb1400_ts_pm_ops,
ucb1400_ts_suspend, ucb1400_ts_resume);

View File

@ -242,8 +242,7 @@ static int wacom_i2c_remove(struct i2c_client *client)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int wacom_i2c_suspend(struct device *dev)
static int __maybe_unused wacom_i2c_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@ -252,7 +251,7 @@ static int wacom_i2c_suspend(struct device *dev)
return 0;
}
static int wacom_i2c_resume(struct device *dev)
static int __maybe_unused wacom_i2c_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@ -260,7 +259,6 @@ static int wacom_i2c_resume(struct device *dev)
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(wacom_i2c_pm, wacom_i2c_suspend, wacom_i2c_resume);

View File

@ -602,8 +602,7 @@ static void zforce_input_close(struct input_dev *dev)
return;
}
#ifdef CONFIG_PM_SLEEP
static int zforce_suspend(struct device *dev)
static int __maybe_unused zforce_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct zforce_ts *ts = i2c_get_clientdata(client);
@ -648,7 +647,7 @@ unlock:
return ret;
}
static int zforce_resume(struct device *dev)
static int __maybe_unused zforce_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct zforce_ts *ts = i2c_get_clientdata(client);
@ -685,7 +684,6 @@ unlock:
return ret;
}
#endif
static SIMPLE_DEV_PM_OPS(zforce_pm_ops, zforce_suspend, zforce_resume);