Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
f20c86cd
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
f20c86cd
编写于
12月 15, 2014
作者:
D
Dmitry Torokhov
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'next' into for-linus
Prepare input updates for 3.19.
上级
a1f9a407
1d6a0136
变更
76
隐藏空白更改
内联
并排
Showing
76 changed file
with
4949 addition
and
581 deletion
+4949
-581
Documentation/devicetree/bindings/input/cap11xx.txt
Documentation/devicetree/bindings/input/cap11xx.txt
+16
-10
Documentation/devicetree/bindings/input/elan_i2c.txt
Documentation/devicetree/bindings/input/elan_i2c.txt
+34
-0
Documentation/devicetree/bindings/input/elants_i2c.txt
Documentation/devicetree/bindings/input/elants_i2c.txt
+33
-0
Documentation/devicetree/bindings/input/gpio-keys.txt
Documentation/devicetree/bindings/input/gpio-keys.txt
+9
-1
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
+1
-0
MAINTAINERS
MAINTAINERS
+6
-0
drivers/input/gameport/gameport.c
drivers/input/gameport/gameport.c
+2
-2
drivers/input/input.c
drivers/input/input.c
+2
-2
drivers/input/joystick/xpad.c
drivers/input/joystick/xpad.c
+4
-4
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Kconfig
+4
-4
drivers/input/keyboard/Makefile
drivers/input/keyboard/Makefile
+1
-1
drivers/input/keyboard/amikbd.c
drivers/input/keyboard/amikbd.c
+30
-17
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/atkbd.c
+4
-2
drivers/input/keyboard/cap11xx.c
drivers/input/keyboard/cap11xx.c
+376
-0
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/gpio_keys.c
+21
-16
drivers/input/keyboard/lm8323.c
drivers/input/keyboard/lm8323.c
+2
-0
drivers/input/keyboard/lpc32xx-keys.c
drivers/input/keyboard/lpc32xx-keys.c
+20
-72
drivers/input/keyboard/mpr121_touchkey.c
drivers/input/keyboard/mpr121_touchkey.c
+12
-30
drivers/input/keyboard/pxa27x_keypad.c
drivers/input/keyboard/pxa27x_keypad.c
+20
-64
drivers/input/misc/88pm860x_onkey.c
drivers/input/misc/88pm860x_onkey.c
+2
-4
drivers/input/misc/ad714x-i2c.c
drivers/input/misc/ad714x-i2c.c
+2
-4
drivers/input/misc/ad714x-spi.c
drivers/input/misc/ad714x-spi.c
+2
-4
drivers/input/misc/adxl34x-i2c.c
drivers/input/misc/adxl34x-i2c.c
+2
-4
drivers/input/misc/adxl34x-spi.c
drivers/input/misc/adxl34x-spi.c
+2
-4
drivers/input/misc/drv260x.c
drivers/input/misc/drv260x.c
+2
-4
drivers/input/misc/drv2667.c
drivers/input/misc/drv2667.c
+2
-4
drivers/input/misc/gp2ap002a00f.c
drivers/input/misc/gp2ap002a00f.c
+2
-4
drivers/input/misc/ims-pcu.c
drivers/input/misc/ims-pcu.c
+2
-2
drivers/input/misc/kxtj9.c
drivers/input/misc/kxtj9.c
+2
-4
drivers/input/misc/max77693-haptic.c
drivers/input/misc/max77693-haptic.c
+2
-4
drivers/input/misc/max8925_onkey.c
drivers/input/misc/max8925_onkey.c
+2
-4
drivers/input/misc/max8997_haptic.c
drivers/input/misc/max8997_haptic.c
+1
-3
drivers/input/misc/palmas-pwrbutton.c
drivers/input/misc/palmas-pwrbutton.c
+2
-4
drivers/input/misc/pm8xxx-vibrator.c
drivers/input/misc/pm8xxx-vibrator.c
+1
-3
drivers/input/misc/pmic8xxx-pwrkey.c
drivers/input/misc/pmic8xxx-pwrkey.c
+2
-4
drivers/input/misc/pwm-beeper.c
drivers/input/misc/pwm-beeper.c
+3
-3
drivers/input/misc/sirfsoc-onkey.c
drivers/input/misc/sirfsoc-onkey.c
+1
-3
drivers/input/misc/twl4030-vibra.c
drivers/input/misc/twl4030-vibra.c
+2
-4
drivers/input/misc/twl6040-vibra.c
drivers/input/misc/twl6040-vibra.c
+1
-3
drivers/input/mouse/Kconfig
drivers/input/mouse/Kconfig
+30
-0
drivers/input/mouse/Makefile
drivers/input/mouse/Makefile
+5
-0
drivers/input/mouse/cyapa.c
drivers/input/mouse/cyapa.c
+156
-133
drivers/input/mouse/elan_i2c.h
drivers/input/mouse/elan_i2c.h
+86
-0
drivers/input/mouse/elan_i2c_core.c
drivers/input/mouse/elan_i2c_core.c
+1137
-0
drivers/input/mouse/elan_i2c_i2c.c
drivers/input/mouse/elan_i2c_i2c.c
+611
-0
drivers/input/mouse/elan_i2c_smbus.c
drivers/input/mouse/elan_i2c_smbus.c
+514
-0
drivers/input/mouse/lifebook.h
drivers/input/mouse/lifebook.h
+3
-3
drivers/input/mouse/navpoint.c
drivers/input/mouse/navpoint.c
+2
-4
drivers/input/mouse/synaptics_i2c.c
drivers/input/mouse/synaptics_i2c.c
+2
-4
drivers/input/serio/altera_ps2.c
drivers/input/serio/altera_ps2.c
+24
-57
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/i8042-x86ia64io.h
+10
-0
drivers/input/serio/serio.c
drivers/input/serio/serio.c
+2
-2
drivers/input/serio/serio_raw.c
drivers/input/serio/serio_raw.c
+2
-2
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Kconfig
+25
-0
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/Makefile
+2
-0
drivers/input/touchscreen/ad7877.c
drivers/input/touchscreen/ad7877.c
+2
-4
drivers/input/touchscreen/ad7879.c
drivers/input/touchscreen/ad7879.c
+2
-4
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/ads7846.c
+2
-4
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/input/touchscreen/atmel_mxt_ts.c
+2
-4
drivers/input/touchscreen/auo-pixcir-ts.c
drivers/input/touchscreen/auo-pixcir-ts.c
+2
-4
drivers/input/touchscreen/cy8ctmg110_ts.c
drivers/input/touchscreen/cy8ctmg110_ts.c
+2
-4
drivers/input/touchscreen/cyttsp_core.c
drivers/input/touchscreen/cyttsp_core.c
+2
-5
drivers/input/touchscreen/edt-ft5x06.c
drivers/input/touchscreen/edt-ft5x06.c
+2
-4
drivers/input/touchscreen/eeti_ts.c
drivers/input/touchscreen/eeti_ts.c
+2
-4
drivers/input/touchscreen/egalax_ts.c
drivers/input/touchscreen/egalax_ts.c
+2
-4
drivers/input/touchscreen/elants_i2c.c
drivers/input/touchscreen/elants_i2c.c
+1271
-0
drivers/input/touchscreen/goodix.c
drivers/input/touchscreen/goodix.c
+395
-0
drivers/input/touchscreen/ili210x.c
drivers/input/touchscreen/ili210x.c
+2
-4
drivers/input/touchscreen/ipaq-micro-ts.c
drivers/input/touchscreen/ipaq-micro-ts.c
+2
-4
drivers/input/touchscreen/mms114.c
drivers/input/touchscreen/mms114.c
+2
-4
drivers/input/touchscreen/pixcir_i2c_ts.c
drivers/input/touchscreen/pixcir_i2c_ts.c
+2
-4
drivers/input/touchscreen/st1232.c
drivers/input/touchscreen/st1232.c
+2
-5
drivers/input/touchscreen/tsc2005.c
drivers/input/touchscreen/tsc2005.c
+2
-4
drivers/input/touchscreen/ucb1400_ts.c
drivers/input/touchscreen/ucb1400_ts.c
+2
-4
drivers/input/touchscreen/wacom_i2c.c
drivers/input/touchscreen/wacom_i2c.c
+2
-4
drivers/input/touchscreen/zforce_ts.c
drivers/input/touchscreen/zforce_ts.c
+2
-4
未找到文件。
Documentation/devicetree/bindings/input/cap11
06
.txt
→
Documentation/devicetree/bindings/input/cap11
xx
.txt
浏览文件 @
f20c86cd
Device tree bindings for Microchip CAP11
06, 6 channel capacitive touch sensor
Device tree bindings for Microchip CAP11
xx based capacitive touch sensors
The node for this d
river
must be a child of a I2C controller node, as the
The node for this d
evice
must be a child of a I2C controller node, as the
device communication via I2C only.
device communication via I2C only.
Required properties:
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.
reg: The I2C slave address of the device.
Only 0x28 is valid.
interrupts: Property describing the interrupt line the
interrupts: Property describing the interrupt line the
device's ALERT#/CM_IRQ# pin is connected to.
device's ALERT#/CM_IRQ# pin is connected to.
...
@@ -26,6 +28,10 @@ Optional properties:
...
@@ -26,6 +28,10 @@ Optional properties:
Valid values are 1, 2, 4, and 8.
Valid values are 1, 2, 4, and 8.
By default, a gain of 1 is set.
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
linux,keycodes: Specifies an array of numeric keycode values to
be used for the channels. If this property is
be used for the channels. If this property is
omitted, KEY_A, KEY_B, etc are used as
omitted, KEY_A, KEY_B, etc are used as
...
@@ -43,11 +49,11 @@ i2c_controller {
...
@@ -43,11 +49,11 @@ i2c_controller {
autorepeat;
autorepeat;
microchip,sensor-gain = <2>;
microchip,sensor-gain = <2>;
linux,keycodes = <103 /* KEY_UP */
linux,keycodes = <103
>,
/* KEY_UP */
106
/* KEY_RIGHT */
<106>,
/* KEY_RIGHT */
108
/* KEY_DOWN */
<108>,
/* KEY_DOWN */
105
/* KEY_LEFT */
<105>,
/* KEY_LEFT */
109
/* KEY_PAGEDOWN */
<109>,
/* KEY_PAGEDOWN */
104>; /* KEY_PAGEUP */
<
104>; /* KEY_PAGEUP */
};
};
}
}
Documentation/devicetree/bindings/input/elan_i2c.txt
0 → 100644
浏览文件 @
f20c86cd
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;
};
/* ... */
};
Documentation/devicetree/bindings/input/elants_i2c.txt
0 → 100644
浏览文件 @
f20c86cd
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;
};
/* ... */
};
Documentation/devicetree/bindings/input/gpio-keys.txt
浏览文件 @
f20c86cd
...
@@ -10,10 +10,13 @@ Optional properties:
...
@@ -10,10 +10,13 @@ Optional properties:
Each button (key) is represented as a sub-node of "gpio-keys":
Each button (key) is represented as a sub-node of "gpio-keys":
Subnode properties:
Subnode properties:
- gpios: OF device-tree gpio specification.
- label: Descriptive name of the key.
- label: Descriptive name of the key.
- linux,code: Keycode to emit.
- 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:
Optional subnode-properties:
- linux,input-type: Specify event type this button/key generates.
- linux,input-type: Specify event type this button/key generates.
If not specified defaults to <1> == EV_KEY.
If not specified defaults to <1> == EV_KEY.
...
@@ -33,4 +36,9 @@ Example nodes:
...
@@ -33,4 +36,9 @@ Example nodes:
linux,code = <103>;
linux,code = <103>;
gpios = <&gpio1 0 1>;
gpios = <&gpio1 0 1>;
};
};
button@22 {
label = "GPIO Key DOWN";
linux,code = <108>;
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
};
...
...
Documentation/devicetree/bindings/vendor-prefixes.txt
浏览文件 @
f20c86cd
...
@@ -42,6 +42,7 @@ dlink D-Link Corporation
...
@@ -42,6 +42,7 @@ dlink D-Link Corporation
dmo Data Modul AG
dmo Data Modul AG
ebv EBV Elektronik
ebv EBV Elektronik
edt Emerging Display Technologies
edt Emerging Display Technologies
elan Elan Microelectronic Corp.
emmicro EM Microelectronic
emmicro EM Microelectronic
epcos EPCOS AG
epcos EPCOS AG
epfl Ecole Polytechnique Fédérale de Lausanne
epfl Ecole Polytechnique Fédérale de Lausanne
...
...
MAINTAINERS
浏览文件 @
f20c86cd
...
@@ -4062,6 +4062,12 @@ L: linux-media@vger.kernel.org
...
@@ -4062,6 +4062,12 @@ L: linux-media@vger.kernel.org
S: Maintained
S: Maintained
F: drivers/media/usb/go7007/
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
GPIO SUBSYSTEM
M: Linus Walleij <linus.walleij@linaro.org>
M: Linus Walleij <linus.walleij@linaro.org>
M: Alexandre Courbot <gnurou@gmail.com>
M: Alexandre Courbot <gnurou@gmail.com>
...
...
drivers/input/gameport/gameport.c
浏览文件 @
f20c86cd
...
@@ -527,14 +527,14 @@ EXPORT_SYMBOL(gameport_set_phys);
...
@@ -527,14 +527,14 @@ EXPORT_SYMBOL(gameport_set_phys);
*/
*/
static
void
gameport_init_port
(
struct
gameport
*
gameport
)
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
);
__module_get
(
THIS_MODULE
);
mutex_init
(
&
gameport
->
drv_mutex
);
mutex_init
(
&
gameport
->
drv_mutex
);
device_initialize
(
&
gameport
->
dev
);
device_initialize
(
&
gameport
->
dev
);
dev_set_name
(
&
gameport
->
dev
,
"gameport%lu"
,
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
.
bus
=
&
gameport_bus
;
gameport
->
dev
.
release
=
gameport_release_port
;
gameport
->
dev
.
release
=
gameport_release_port
;
if
(
gameport
->
parent
)
if
(
gameport
->
parent
)
...
...
drivers/input/input.c
浏览文件 @
f20c86cd
...
@@ -1775,7 +1775,7 @@ EXPORT_SYMBOL_GPL(input_class);
...
@@ -1775,7 +1775,7 @@ EXPORT_SYMBOL_GPL(input_class);
*/
*/
struct
input_dev
*
input_allocate_device
(
void
)
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
;
struct
input_dev
*
dev
;
dev
=
kzalloc
(
sizeof
(
struct
input_dev
),
GFP_KERNEL
);
dev
=
kzalloc
(
sizeof
(
struct
input_dev
),
GFP_KERNEL
);
...
@@ -1790,7 +1790,7 @@ struct input_dev *input_allocate_device(void)
...
@@ -1790,7 +1790,7 @@ struct input_dev *input_allocate_device(void)
INIT_LIST_HEAD
(
&
dev
->
node
);
INIT_LIST_HEAD
(
&
dev
->
node
);
dev_set_name
(
&
dev
->
dev
,
"input%lu"
,
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
);
__module_get
(
THIS_MODULE
);
}
}
...
...
drivers/input/joystick/xpad.c
浏览文件 @
f20c86cd
...
@@ -886,8 +886,8 @@ static void xpad_led_set(struct led_classdev *led_cdev,
...
@@ -886,8 +886,8 @@ static void xpad_led_set(struct led_classdev *led_cdev,
static
int
xpad_led_probe
(
struct
usb_xpad
*
xpad
)
static
int
xpad_led_probe
(
struct
usb_xpad
*
xpad
)
{
{
static
atomic_t
led_seq
=
ATOMIC_INIT
(
0
);
static
atomic_t
led_seq
=
ATOMIC_INIT
(
-
1
);
long
led_no
;
unsigned
long
led_no
;
struct
xpad_led
*
led
;
struct
xpad_led
*
led
;
struct
led_classdev
*
led_cdev
;
struct
led_classdev
*
led_cdev
;
int
error
;
int
error
;
...
@@ -899,9 +899,9 @@ static int xpad_led_probe(struct usb_xpad *xpad)
...
@@ -899,9 +899,9 @@ static int xpad_led_probe(struct usb_xpad *xpad)
if
(
!
led
)
if
(
!
led
)
return
-
ENOMEM
;
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%l
d
"
,
led_no
);
snprintf
(
led
->
name
,
sizeof
(
led
->
name
),
"xpad%l
u
"
,
led_no
);
led
->
xpad
=
xpad
;
led
->
xpad
=
xpad
;
led_cdev
=
&
led
->
led_cdev
;
led_cdev
=
&
led
->
led_cdev
;
...
...
drivers/input/keyboard/Kconfig
浏览文件 @
f20c86cd
...
@@ -665,14 +665,14 @@ config KEYBOARD_CROS_EC
...
@@ -665,14 +665,14 @@ config KEYBOARD_CROS_EC
To compile this driver as a module, choose M here: the
To compile this driver as a module, choose M here: the
module will be called cros_ec_keyb.
module will be called cros_ec_keyb.
config KEYBOARD_CAP11
06
config KEYBOARD_CAP11
XX
tristate "Microchip CAP11
06 touch sensor
"
tristate "Microchip CAP11
XX based touch sensors
"
depends on OF && I2C
depends on OF && I2C
select REGMAP_I2C
select REGMAP_I2C
help
help
Say Y here to enable the CAP11
06
touch sensor driver.
Say Y here to enable the CAP11
XX
touch sensor driver.
To compile this driver as a module, choose M here: the
To compile this driver as a module, choose M here: the
module will be called cap11
06
.
module will be called cap11
xx
.
endif
endif
drivers/input/keyboard/Makefile
浏览文件 @
f20c86cd
...
@@ -11,7 +11,7 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
...
@@ -11,7 +11,7 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
obj-$(CONFIG_KEYBOARD_ATARI)
+=
atakbd.o
obj-$(CONFIG_KEYBOARD_ATARI)
+=
atakbd.o
obj-$(CONFIG_KEYBOARD_ATKBD)
+=
atkbd.o
obj-$(CONFIG_KEYBOARD_ATKBD)
+=
atkbd.o
obj-$(CONFIG_KEYBOARD_BFIN)
+=
bf54x-keys.o
obj-$(CONFIG_KEYBOARD_BFIN)
+=
bf54x-keys.o
obj-$(CONFIG_KEYBOARD_CAP11
06)
+=
cap1106
.o
obj-$(CONFIG_KEYBOARD_CAP11
XX)
+=
cap11xx
.o
obj-$(CONFIG_KEYBOARD_CLPS711X)
+=
clps711x-keypad.o
obj-$(CONFIG_KEYBOARD_CLPS711X)
+=
clps711x-keypad.o
obj-$(CONFIG_KEYBOARD_CROS_EC)
+=
cros_ec_keyb.o
obj-$(CONFIG_KEYBOARD_CROS_EC)
+=
cros_ec_keyb.o
obj-$(CONFIG_KEYBOARD_DAVINCI)
+=
davinci_keyscan.o
obj-$(CONFIG_KEYBOARD_DAVINCI)
+=
davinci_keyscan.o
...
...
drivers/input/keyboard/amikbd.c
浏览文件 @
f20c86cd
...
@@ -45,6 +45,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
...
@@ -45,6 +45,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION
(
"Amiga keyboard driver"
);
MODULE_DESCRIPTION
(
"Amiga keyboard driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
#ifdef CONFIG_HW_CONSOLE
static
unsigned
char
amikbd_keycode
[
0x78
]
__initdata
=
{
static
unsigned
char
amikbd_keycode
[
0x78
]
__initdata
=
{
[
0
]
=
KEY_GRAVE
,
[
0
]
=
KEY_GRAVE
,
[
1
]
=
KEY_1
,
[
1
]
=
KEY_1
,
...
@@ -144,6 +145,32 @@ static unsigned char amikbd_keycode[0x78] __initdata = {
...
@@ -144,6 +145,32 @@ static unsigned char amikbd_keycode[0x78] __initdata = {
[
103
]
=
KEY_RIGHTMETA
[
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
]
=
{
static
const
char
*
amikbd_messages
[
8
]
=
{
[
0
]
=
KERN_ALERT
"amikbd: Ctrl-Amiga-Amiga reset warning!!
\n
"
,
[
0
]
=
KERN_ALERT
"amikbd: Ctrl-Amiga-Amiga reset warning!!
\n
"
,
[
1
]
=
KERN_WARNING
"amikbd: keyboard lost sync
\n
"
,
[
1
]
=
KERN_WARNING
"amikbd: keyboard lost sync
\n
"
,
...
@@ -186,7 +213,7 @@ static irqreturn_t amikbd_interrupt(int irq, void *data)
...
@@ -186,7 +213,7 @@ static irqreturn_t amikbd_interrupt(int irq, void *data)
static
int
__init
amikbd_probe
(
struct
platform_device
*
pdev
)
static
int
__init
amikbd_probe
(
struct
platform_device
*
pdev
)
{
{
struct
input_dev
*
dev
;
struct
input_dev
*
dev
;
int
i
,
j
,
err
;
int
i
,
err
;
dev
=
input_allocate_device
();
dev
=
input_allocate_device
();
if
(
!
dev
)
{
if
(
!
dev
)
{
...
@@ -207,22 +234,8 @@ static int __init amikbd_probe(struct platform_device *pdev)
...
@@ -207,22 +234,8 @@ static int __init amikbd_probe(struct platform_device *pdev)
for
(
i
=
0
;
i
<
0x78
;
i
++
)
for
(
i
=
0
;
i
<
0x78
;
i
++
)
set_bit
(
i
,
dev
->
keybit
);
set_bit
(
i
,
dev
->
keybit
);
for
(
i
=
0
;
i
<
MAX_NR_KEYMAPS
;
i
++
)
{
amikbd_init_console_keymaps
();
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
));
}
ciaa
.
cra
&=
~
0x41
;
/* serial data in, turn off TA */
ciaa
.
cra
&=
~
0x41
;
/* serial data in, turn off TA */
err
=
request_irq
(
IRQ_AMIGA_CIAA_SP
,
amikbd_interrupt
,
0
,
"amikbd"
,
err
=
request_irq
(
IRQ_AMIGA_CIAA_SP
,
amikbd_interrupt
,
0
,
"amikbd"
,
dev
);
dev
);
...
...
drivers/input/keyboard/atkbd.c
浏览文件 @
f20c86cd
...
@@ -456,8 +456,9 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
...
@@ -456,8 +456,9 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
keycode
=
atkbd
->
keycode
[
code
];
keycode
=
atkbd
->
keycode
[
code
];
if
(
keycode
!=
ATKBD_KEY_NULL
)
if
(
!
(
atkbd
->
release
&&
test_bit
(
code
,
atkbd
->
force_release_mask
)))
input_event
(
dev
,
EV_MSC
,
MSC_SCAN
,
code
);
if
(
keycode
!=
ATKBD_KEY_NULL
)
input_event
(
dev
,
EV_MSC
,
MSC_SCAN
,
code
);
switch
(
keycode
)
{
switch
(
keycode
)
{
case
ATKBD_KEY_NULL
:
case
ATKBD_KEY_NULL
:
...
@@ -511,6 +512,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
...
@@ -511,6 +512,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
input_sync
(
dev
);
input_sync
(
dev
);
if
(
value
&&
test_bit
(
code
,
atkbd
->
force_release_mask
))
{
if
(
value
&&
test_bit
(
code
,
atkbd
->
force_release_mask
))
{
input_event
(
dev
,
EV_MSC
,
MSC_SCAN
,
code
);
input_report_key
(
dev
,
keycode
,
0
);
input_report_key
(
dev
,
keycode
,
0
);
input_sync
(
dev
);
input_sync
(
dev
);
}
}
...
...
drivers/input/keyboard/cap11
06
.c
→
drivers/input/keyboard/cap11
xx
.c
浏览文件 @
f20c86cd
/*
/*
* Input driver for Microchip CAP1106, 6 channel capacitive touch sensor
* Input driver for Microchip CAP11xx based capacitive touch sensors
*
* http://www.microchip.com/wwwproducts/Devices.aspx?product=CAP1106
*
*
* (c) 2014 Daniel Mack <linux@zonque.org>
* (c) 2014 Daniel Mack <linux@zonque.org>
*
*
...
@@ -19,123 +17,139 @@
...
@@ -19,123 +17,139 @@
#include <linux/i2c.h>
#include <linux/i2c.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/consumer.h>
#define CAP1106_REG_MAIN_CONTROL 0x00
#define CAP11XX_REG_MAIN_CONTROL 0x00
#define CAP1106_REG_MAIN_CONTROL_GAIN_SHIFT (6)
#define CAP11XX_REG_MAIN_CONTROL_GAIN_SHIFT (6)
#define CAP1106_REG_MAIN_CONTROL_GAIN_MASK (0xc0)
#define CAP11XX_REG_MAIN_CONTROL_GAIN_MASK (0xc0)
#define CAP1106_REG_MAIN_CONTROL_DLSEEP BIT(4)
#define CAP11XX_REG_MAIN_CONTROL_DLSEEP BIT(4)
#define CAP1106_REG_GENERAL_STATUS 0x02
#define CAP11XX_REG_GENERAL_STATUS 0x02
#define CAP1106_REG_SENSOR_INPUT 0x03
#define CAP11XX_REG_SENSOR_INPUT 0x03
#define CAP1106_REG_NOISE_FLAG_STATUS 0x0a
#define CAP11XX_REG_NOISE_FLAG_STATUS 0x0a
#define CAP1106_REG_SENOR_DELTA(X) (0x10 + (X))
#define CAP11XX_REG_SENOR_DELTA(X) (0x10 + (X))
#define CAP1106_REG_SENSITIVITY_CONTROL 0x1f
#define CAP11XX_REG_SENSITIVITY_CONTROL 0x1f
#define CAP1106_REG_CONFIG 0x20
#define CAP11XX_REG_CONFIG 0x20
#define CAP1106_REG_SENSOR_ENABLE 0x21
#define CAP11XX_REG_SENSOR_ENABLE 0x21
#define CAP1106_REG_SENSOR_CONFIG 0x22
#define CAP11XX_REG_SENSOR_CONFIG 0x22
#define CAP1106_REG_SENSOR_CONFIG2 0x23
#define CAP11XX_REG_SENSOR_CONFIG2 0x23
#define CAP1106_REG_SAMPLING_CONFIG 0x24
#define CAP11XX_REG_SAMPLING_CONFIG 0x24
#define CAP1106_REG_CALIBRATION 0x26
#define CAP11XX_REG_CALIBRATION 0x26
#define CAP1106_REG_INT_ENABLE 0x27
#define CAP11XX_REG_INT_ENABLE 0x27
#define CAP1106_REG_REPEAT_RATE 0x28
#define CAP11XX_REG_REPEAT_RATE 0x28
#define CAP1106_REG_MT_CONFIG 0x2a
#define CAP11XX_REG_MT_CONFIG 0x2a
#define CAP1106_REG_MT_PATTERN_CONFIG 0x2b
#define CAP11XX_REG_MT_PATTERN_CONFIG 0x2b
#define CAP1106_REG_MT_PATTERN 0x2d
#define CAP11XX_REG_MT_PATTERN 0x2d
#define CAP1106_REG_RECALIB_CONFIG 0x2f
#define CAP11XX_REG_RECALIB_CONFIG 0x2f
#define CAP1106_REG_SENSOR_THRESH(X) (0x30 + (X))
#define CAP11XX_REG_SENSOR_THRESH(X) (0x30 + (X))
#define CAP1106_REG_SENSOR_NOISE_THRESH 0x38
#define CAP11XX_REG_SENSOR_NOISE_THRESH 0x38
#define CAP1106_REG_STANDBY_CHANNEL 0x40
#define CAP11XX_REG_STANDBY_CHANNEL 0x40
#define CAP1106_REG_STANDBY_CONFIG 0x41
#define CAP11XX_REG_STANDBY_CONFIG 0x41
#define CAP1106_REG_STANDBY_SENSITIVITY 0x42
#define CAP11XX_REG_STANDBY_SENSITIVITY 0x42
#define CAP1106_REG_STANDBY_THRESH 0x43
#define CAP11XX_REG_STANDBY_THRESH 0x43
#define CAP1106_REG_CONFIG2 0x44
#define CAP11XX_REG_CONFIG2 0x44
#define CAP1106_REG_SENSOR_BASE_CNT(X) (0x50 + (X))
#define CAP11XX_REG_CONFIG2_ALT_POL BIT(6)
#define CAP1106_REG_SENSOR_CALIB (0xb1 + (X))
#define CAP11XX_REG_SENSOR_BASE_CNT(X) (0x50 + (X))
#define CAP1106_REG_SENSOR_CALIB_LSB1 0xb9
#define CAP11XX_REG_SENSOR_CALIB (0xb1 + (X))
#define CAP1106_REG_SENSOR_CALIB_LSB2 0xba
#define CAP11XX_REG_SENSOR_CALIB_LSB1 0xb9
#define CAP1106_REG_PRODUCT_ID 0xfd
#define CAP11XX_REG_SENSOR_CALIB_LSB2 0xba
#define CAP1106_REG_MANUFACTURER_ID 0xfe
#define CAP11XX_REG_PRODUCT_ID 0xfd
#define CAP1106_REG_REVISION 0xff
#define CAP11XX_REG_MANUFACTURER_ID 0xfe
#define CAP11XX_REG_REVISION 0xff
#define CAP1106_NUM_CHN 6
#define CAP1106_PRODUCT_ID 0x55
#define CAP11XX_MANUFACTURER_ID 0x5d
#define CAP1106_MANUFACTURER_ID 0x5d
struct
cap11xx_priv
{
struct
cap1106_priv
{
struct
regmap
*
regmap
;
struct
regmap
*
regmap
;
struct
input_dev
*
idev
;
struct
input_dev
*
idev
;
/* config */
/* config */
unsigned
short
keycodes
[
CAP1106_NUM_CHN
];
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
cap11
06
_reg_defaults
[]
=
{
static
const
struct
reg_default
cap11
xx
_reg_defaults
[]
=
{
{
CAP11
06
_REG_MAIN_CONTROL
,
0x00
},
{
CAP11
XX
_REG_MAIN_CONTROL
,
0x00
},
{
CAP11
06
_REG_GENERAL_STATUS
,
0x00
},
{
CAP11
XX
_REG_GENERAL_STATUS
,
0x00
},
{
CAP11
06
_REG_SENSOR_INPUT
,
0x00
},
{
CAP11
XX
_REG_SENSOR_INPUT
,
0x00
},
{
CAP11
06
_REG_NOISE_FLAG_STATUS
,
0x00
},
{
CAP11
XX
_REG_NOISE_FLAG_STATUS
,
0x00
},
{
CAP11
06
_REG_SENSITIVITY_CONTROL
,
0x2f
},
{
CAP11
XX
_REG_SENSITIVITY_CONTROL
,
0x2f
},
{
CAP11
06
_REG_CONFIG
,
0x20
},
{
CAP11
XX
_REG_CONFIG
,
0x20
},
{
CAP11
06
_REG_SENSOR_ENABLE
,
0x3f
},
{
CAP11
XX
_REG_SENSOR_ENABLE
,
0x3f
},
{
CAP11
06
_REG_SENSOR_CONFIG
,
0xa4
},
{
CAP11
XX
_REG_SENSOR_CONFIG
,
0xa4
},
{
CAP11
06
_REG_SENSOR_CONFIG2
,
0x07
},
{
CAP11
XX
_REG_SENSOR_CONFIG2
,
0x07
},
{
CAP11
06
_REG_SAMPLING_CONFIG
,
0x39
},
{
CAP11
XX
_REG_SAMPLING_CONFIG
,
0x39
},
{
CAP11
06
_REG_CALIBRATION
,
0x00
},
{
CAP11
XX
_REG_CALIBRATION
,
0x00
},
{
CAP11
06
_REG_INT_ENABLE
,
0x3f
},
{
CAP11
XX
_REG_INT_ENABLE
,
0x3f
},
{
CAP11
06
_REG_REPEAT_RATE
,
0x3f
},
{
CAP11
XX
_REG_REPEAT_RATE
,
0x3f
},
{
CAP11
06
_REG_MT_CONFIG
,
0x80
},
{
CAP11
XX
_REG_MT_CONFIG
,
0x80
},
{
CAP11
06
_REG_MT_PATTERN_CONFIG
,
0x00
},
{
CAP11
XX
_REG_MT_PATTERN_CONFIG
,
0x00
},
{
CAP11
06
_REG_MT_PATTERN
,
0x3f
},
{
CAP11
XX
_REG_MT_PATTERN
,
0x3f
},
{
CAP11
06
_REG_RECALIB_CONFIG
,
0x8a
},
{
CAP11
XX
_REG_RECALIB_CONFIG
,
0x8a
},
{
CAP11
06
_REG_SENSOR_THRESH
(
0
),
0x40
},
{
CAP11
XX
_REG_SENSOR_THRESH
(
0
),
0x40
},
{
CAP11
06
_REG_SENSOR_THRESH
(
1
),
0x40
},
{
CAP11
XX
_REG_SENSOR_THRESH
(
1
),
0x40
},
{
CAP11
06
_REG_SENSOR_THRESH
(
2
),
0x40
},
{
CAP11
XX
_REG_SENSOR_THRESH
(
2
),
0x40
},
{
CAP11
06
_REG_SENSOR_THRESH
(
3
),
0x40
},
{
CAP11
XX
_REG_SENSOR_THRESH
(
3
),
0x40
},
{
CAP11
06
_REG_SENSOR_THRESH
(
4
),
0x40
},
{
CAP11
XX
_REG_SENSOR_THRESH
(
4
),
0x40
},
{
CAP11
06
_REG_SENSOR_THRESH
(
5
),
0x40
},
{
CAP11
XX
_REG_SENSOR_THRESH
(
5
),
0x40
},
{
CAP11
06
_REG_SENSOR_NOISE_THRESH
,
0x01
},
{
CAP11
XX
_REG_SENSOR_NOISE_THRESH
,
0x01
},
{
CAP11
06
_REG_STANDBY_CHANNEL
,
0x00
},
{
CAP11
XX
_REG_STANDBY_CHANNEL
,
0x00
},
{
CAP11
06
_REG_STANDBY_CONFIG
,
0x39
},
{
CAP11
XX
_REG_STANDBY_CONFIG
,
0x39
},
{
CAP11
06
_REG_STANDBY_SENSITIVITY
,
0x02
},
{
CAP11
XX
_REG_STANDBY_SENSITIVITY
,
0x02
},
{
CAP11
06
_REG_STANDBY_THRESH
,
0x40
},
{
CAP11
XX
_REG_STANDBY_THRESH
,
0x40
},
{
CAP11
06
_REG_CONFIG2
,
0x40
},
{
CAP11
XX
_REG_CONFIG2
,
0x40
},
{
CAP11
06
_REG_SENSOR_CALIB_LSB1
,
0x00
},
{
CAP11
XX
_REG_SENSOR_CALIB_LSB1
,
0x00
},
{
CAP11
06
_REG_SENSOR_CALIB_LSB2
,
0x00
},
{
CAP11
XX
_REG_SENSOR_CALIB_LSB2
,
0x00
},
};
};
static
bool
cap11
06
_volatile_reg
(
struct
device
*
dev
,
unsigned
int
reg
)
static
bool
cap11
xx
_volatile_reg
(
struct
device
*
dev
,
unsigned
int
reg
)
{
{
switch
(
reg
)
{
switch
(
reg
)
{
case
CAP11
06
_REG_MAIN_CONTROL
:
case
CAP11
XX
_REG_MAIN_CONTROL
:
case
CAP11
06
_REG_SENSOR_INPUT
:
case
CAP11
XX
_REG_SENSOR_INPUT
:
case
CAP11
06
_REG_SENOR_DELTA
(
0
):
case
CAP11
XX
_REG_SENOR_DELTA
(
0
):
case
CAP11
06
_REG_SENOR_DELTA
(
1
):
case
CAP11
XX
_REG_SENOR_DELTA
(
1
):
case
CAP11
06
_REG_SENOR_DELTA
(
2
):
case
CAP11
XX
_REG_SENOR_DELTA
(
2
):
case
CAP11
06
_REG_SENOR_DELTA
(
3
):
case
CAP11
XX
_REG_SENOR_DELTA
(
3
):
case
CAP11
06
_REG_SENOR_DELTA
(
4
):
case
CAP11
XX
_REG_SENOR_DELTA
(
4
):
case
CAP11
06
_REG_SENOR_DELTA
(
5
):
case
CAP11
XX
_REG_SENOR_DELTA
(
5
):
case
CAP11
06
_REG_PRODUCT_ID
:
case
CAP11
XX
_REG_PRODUCT_ID
:
case
CAP11
06
_REG_MANUFACTURER_ID
:
case
CAP11
XX
_REG_MANUFACTURER_ID
:
case
CAP11
06
_REG_REVISION
:
case
CAP11
XX
_REG_REVISION
:
return
true
;
return
true
;
}
}
return
false
;
return
false
;
}
}
static
const
struct
regmap_config
cap11
06
_regmap_config
=
{
static
const
struct
regmap_config
cap11
xx
_regmap_config
=
{
.
reg_bits
=
8
,
.
reg_bits
=
8
,
.
val_bits
=
8
,
.
val_bits
=
8
,
.
max_register
=
CAP11
06
_REG_REVISION
,
.
max_register
=
CAP11
XX
_REG_REVISION
,
.
reg_defaults
=
cap11
06
_reg_defaults
,
.
reg_defaults
=
cap11
xx
_reg_defaults
,
.
num_reg_defaults
=
ARRAY_SIZE
(
cap11
06
_reg_defaults
),
.
num_reg_defaults
=
ARRAY_SIZE
(
cap11
xx
_reg_defaults
),
.
cache_type
=
REGCACHE_RBTREE
,
.
cache_type
=
REGCACHE_RBTREE
,
.
volatile_reg
=
cap11
06
_volatile_reg
,
.
volatile_reg
=
cap11
xx
_volatile_reg
,
};
};
static
irqreturn_t
cap11
06
_thread_func
(
int
irq_num
,
void
*
data
)
static
irqreturn_t
cap11
xx
_thread_func
(
int
irq_num
,
void
*
data
)
{
{
struct
cap11
06
_priv
*
priv
=
data
;
struct
cap11
xx
_priv
*
priv
=
data
;
unsigned
int
status
;
unsigned
int
status
;
int
ret
,
i
;
int
ret
,
i
;
...
@@ -143,15 +157,15 @@ static irqreturn_t cap1106_thread_func(int irq_num, void *data)
...
@@ -143,15 +157,15 @@ static irqreturn_t cap1106_thread_func(int irq_num, void *data)
* Deassert interrupt. This needs to be done before reading the status
* Deassert interrupt. This needs to be done before reading the status
* registers, which will not carry valid values otherwise.
* registers, which will not carry valid values otherwise.
*/
*/
ret
=
regmap_update_bits
(
priv
->
regmap
,
CAP11
06
_REG_MAIN_CONTROL
,
1
,
0
);
ret
=
regmap_update_bits
(
priv
->
regmap
,
CAP11
XX
_REG_MAIN_CONTROL
,
1
,
0
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
out
;
goto
out
;
ret
=
regmap_read
(
priv
->
regmap
,
CAP11
06
_REG_SENSOR_INPUT
,
&
status
);
ret
=
regmap_read
(
priv
->
regmap
,
CAP11
XX
_REG_SENSOR_INPUT
,
&
status
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
out
;
goto
out
;
for
(
i
=
0
;
i
<
CAP1106_NUM_CHN
;
i
++
)
for
(
i
=
0
;
i
<
priv
->
idev
->
keycodemax
;
i
++
)
input_report_key
(
priv
->
idev
,
priv
->
keycodes
[
i
],
input_report_key
(
priv
->
idev
,
priv
->
keycodes
[
i
],
status
&
(
1
<<
i
));
status
&
(
1
<<
i
));
...
@@ -161,70 +175,85 @@ static irqreturn_t cap1106_thread_func(int irq_num, void *data)
...
@@ -161,70 +175,85 @@ static irqreturn_t cap1106_thread_func(int irq_num, void *data)
return
IRQ_HANDLED
;
return
IRQ_HANDLED
;
}
}
static
int
cap11
06_set_sleep
(
struct
cap1106
_priv
*
priv
,
bool
sleep
)
static
int
cap11
xx_set_sleep
(
struct
cap11xx
_priv
*
priv
,
bool
sleep
)
{
{
return
regmap_update_bits
(
priv
->
regmap
,
CAP11
06
_REG_MAIN_CONTROL
,
return
regmap_update_bits
(
priv
->
regmap
,
CAP11
XX
_REG_MAIN_CONTROL
,
CAP11
06
_REG_MAIN_CONTROL_DLSEEP
,
CAP11
XX
_REG_MAIN_CONTROL_DLSEEP
,
sleep
?
CAP11
06
_REG_MAIN_CONTROL_DLSEEP
:
0
);
sleep
?
CAP11
XX
_REG_MAIN_CONTROL_DLSEEP
:
0
);
}
}
static
int
cap11
06
_input_open
(
struct
input_dev
*
idev
)
static
int
cap11
xx
_input_open
(
struct
input_dev
*
idev
)
{
{
struct
cap11
06
_priv
*
priv
=
input_get_drvdata
(
idev
);
struct
cap11
xx
_priv
*
priv
=
input_get_drvdata
(
idev
);
return
cap11
06
_set_sleep
(
priv
,
false
);
return
cap11
xx
_set_sleep
(
priv
,
false
);
}
}
static
void
cap11
06
_input_close
(
struct
input_dev
*
idev
)
static
void
cap11
xx
_input_close
(
struct
input_dev
*
idev
)
{
{
struct
cap11
06
_priv
*
priv
=
input_get_drvdata
(
idev
);
struct
cap11
xx
_priv
*
priv
=
input_get_drvdata
(
idev
);
cap11
06
_set_sleep
(
priv
,
true
);
cap11
xx
_set_sleep
(
priv
,
true
);
}
}
static
int
cap11
06
_i2c_probe
(
struct
i2c_client
*
i2c_client
,
static
int
cap11
xx
_i2c_probe
(
struct
i2c_client
*
i2c_client
,
const
struct
i2c_device_id
*
id
)
const
struct
i2c_device_id
*
id
)
{
{
struct
device
*
dev
=
&
i2c_client
->
dev
;
struct
device
*
dev
=
&
i2c_client
->
dev
;
struct
cap11
06
_priv
*
priv
;
struct
cap11
xx
_priv
*
priv
;
struct
device_node
*
node
;
struct
device_node
*
node
;
const
struct
cap11xx_hw_model
*
cap
;
int
i
,
error
,
irq
,
gain
=
0
;
int
i
,
error
,
irq
,
gain
=
0
;
unsigned
int
val
,
rev
;
unsigned
int
val
,
rev
;
u32
gain32
,
keycodes
[
CAP1106_NUM_CHN
]
;
u32
gain32
;
priv
=
devm_kzalloc
(
dev
,
sizeof
(
*
priv
),
GFP_KERNEL
);
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
)
if
(
!
priv
)
return
-
ENOMEM
;
return
-
ENOMEM
;
priv
->
regmap
=
devm_regmap_init_i2c
(
i2c_client
,
&
cap11
06
_regmap_config
);
priv
->
regmap
=
devm_regmap_init_i2c
(
i2c_client
,
&
cap11
xx
_regmap_config
);
if
(
IS_ERR
(
priv
->
regmap
))
if
(
IS_ERR
(
priv
->
regmap
))
return
PTR_ERR
(
priv
->
regmap
);
return
PTR_ERR
(
priv
->
regmap
);
error
=
regmap_read
(
priv
->
regmap
,
CAP11
06
_REG_PRODUCT_ID
,
&
val
);
error
=
regmap_read
(
priv
->
regmap
,
CAP11
XX
_REG_PRODUCT_ID
,
&
val
);
if
(
error
)
if
(
error
)
return
error
;
return
error
;
if
(
val
!=
CAP1106_PRODUCT_ID
)
{
if
(
val
!=
cap
->
product_id
)
{
dev_err
(
dev
,
"Product ID: Got 0x%02x, expected 0x%02x
\n
"
,
dev_err
(
dev
,
"Product ID: Got 0x%02x, expected 0x%02x
\n
"
,
val
,
CAP1106_PRODUCT_ID
);
val
,
cap
->
product_id
);
return
-
EN
ODEV
;
return
-
EN
XIO
;
}
}
error
=
regmap_read
(
priv
->
regmap
,
CAP11
06
_REG_MANUFACTURER_ID
,
&
val
);
error
=
regmap_read
(
priv
->
regmap
,
CAP11
XX
_REG_MANUFACTURER_ID
,
&
val
);
if
(
error
)
if
(
error
)
return
error
;
return
error
;
if
(
val
!=
CAP11
06
_MANUFACTURER_ID
)
{
if
(
val
!=
CAP11
XX
_MANUFACTURER_ID
)
{
dev_err
(
dev
,
"Manufacturer ID: Got 0x%02x, expected 0x%02x
\n
"
,
dev_err
(
dev
,
"Manufacturer ID: Got 0x%02x, expected 0x%02x
\n
"
,
val
,
CAP11
06
_MANUFACTURER_ID
);
val
,
CAP11
XX
_MANUFACTURER_ID
);
return
-
EN
ODEV
;
return
-
EN
XIO
;
}
}
error
=
regmap_read
(
priv
->
regmap
,
CAP11
06
_REG_REVISION
,
&
rev
);
error
=
regmap_read
(
priv
->
regmap
,
CAP11
XX
_REG_REVISION
,
&
rev
);
if
(
error
<
0
)
if
(
error
<
0
)
return
error
;
return
error
;
dev_info
(
dev
,
"CAP11
06
detected, revision 0x%02x
\n
"
,
rev
);
dev_info
(
dev
,
"CAP11
XX
detected, revision 0x%02x
\n
"
,
rev
);
i2c_set_clientdata
(
i2c_client
,
priv
);
i2c_set_clientdata
(
i2c_client
,
priv
);
node
=
dev
->
of_node
;
node
=
dev
->
of_node
;
...
@@ -235,26 +264,28 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,
...
@@ -235,26 +264,28 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,
dev_err
(
dev
,
"Invalid sensor-gain value %d
\n
"
,
gain32
);
dev_err
(
dev
,
"Invalid sensor-gain value %d
\n
"
,
gain32
);
}
}
BUILD_BUG_ON
(
ARRAY_SIZE
(
keycodes
)
!=
ARRAY_SIZE
(
priv
->
keycodes
));
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 */
/* Provide some useful defaults */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
keycodes
)
;
i
++
)
for
(
i
=
0
;
i
<
cap
->
num_channels
;
i
++
)
keycodes
[
i
]
=
KEY_A
+
i
;
priv
->
keycodes
[
i
]
=
KEY_A
+
i
;
of_property_read_u32_array
(
node
,
"linux,keycodes"
,
of_property_read_u32_array
(
node
,
"linux,keycodes"
,
keycodes
,
ARRAY_SIZE
(
keycodes
));
priv
->
keycodes
,
cap
->
num_channels
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
keycodes
);
i
++
)
priv
->
keycodes
[
i
]
=
keycodes
[
i
];
error
=
regmap_update_bits
(
priv
->
regmap
,
CAP11
06
_REG_MAIN_CONTROL
,
error
=
regmap_update_bits
(
priv
->
regmap
,
CAP11
XX
_REG_MAIN_CONTROL
,
CAP11
06
_REG_MAIN_CONTROL_GAIN_MASK
,
CAP11
XX
_REG_MAIN_CONTROL_GAIN_MASK
,
gain
<<
CAP11
06
_REG_MAIN_CONTROL_GAIN_SHIFT
);
gain
<<
CAP11
XX
_REG_MAIN_CONTROL_GAIN_SHIFT
);
if
(
error
)
if
(
error
)
return
error
;
return
error
;
/* Disable autorepeat. The Linux input system has its own handling. */
/* Disable autorepeat. The Linux input system has its own handling. */
error
=
regmap_write
(
priv
->
regmap
,
CAP11
06
_REG_REPEAT_RATE
,
0
);
error
=
regmap_write
(
priv
->
regmap
,
CAP11
XX
_REG_REPEAT_RATE
,
0
);
if
(
error
)
if
(
error
)
return
error
;
return
error
;
...
@@ -262,28 +293,28 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,
...
@@ -262,28 +293,28 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,
if
(
!
priv
->
idev
)
if
(
!
priv
->
idev
)
return
-
ENOMEM
;
return
-
ENOMEM
;
priv
->
idev
->
name
=
"CAP11
06
capacitive touch sensor"
;
priv
->
idev
->
name
=
"CAP11
XX
capacitive touch sensor"
;
priv
->
idev
->
id
.
bustype
=
BUS_I2C
;
priv
->
idev
->
id
.
bustype
=
BUS_I2C
;
priv
->
idev
->
evbit
[
0
]
=
BIT_MASK
(
EV_KEY
);
priv
->
idev
->
evbit
[
0
]
=
BIT_MASK
(
EV_KEY
);
if
(
of_property_read_bool
(
node
,
"autorepeat"
))
if
(
of_property_read_bool
(
node
,
"autorepeat"
))
__set_bit
(
EV_REP
,
priv
->
idev
->
evbit
);
__set_bit
(
EV_REP
,
priv
->
idev
->
evbit
);
for
(
i
=
0
;
i
<
CAP1106_NUM_CHN
;
i
++
)
for
(
i
=
0
;
i
<
cap
->
num_channels
;
i
++
)
__set_bit
(
priv
->
keycodes
[
i
],
priv
->
idev
->
keybit
);
__set_bit
(
priv
->
keycodes
[
i
],
priv
->
idev
->
keybit
);
__clear_bit
(
KEY_RESERVED
,
priv
->
idev
->
keybit
);
__clear_bit
(
KEY_RESERVED
,
priv
->
idev
->
keybit
);
priv
->
idev
->
keycode
=
priv
->
keycodes
;
priv
->
idev
->
keycode
=
priv
->
keycodes
;
priv
->
idev
->
keycodesize
=
sizeof
(
priv
->
keycodes
[
0
]);
priv
->
idev
->
keycodesize
=
sizeof
(
priv
->
keycodes
[
0
]);
priv
->
idev
->
keycodemax
=
ARRAY_SIZE
(
priv
->
keycodes
)
;
priv
->
idev
->
keycodemax
=
cap
->
num_channels
;
priv
->
idev
->
id
.
vendor
=
CAP11
06
_MANUFACTURER_ID
;
priv
->
idev
->
id
.
vendor
=
CAP11
XX
_MANUFACTURER_ID
;
priv
->
idev
->
id
.
product
=
CAP1106_PRODUCT_ID
;
priv
->
idev
->
id
.
product
=
cap
->
product_id
;
priv
->
idev
->
id
.
version
=
rev
;
priv
->
idev
->
id
.
version
=
rev
;
priv
->
idev
->
open
=
cap11
06
_input_open
;
priv
->
idev
->
open
=
cap11
xx
_input_open
;
priv
->
idev
->
close
=
cap11
06
_input_close
;
priv
->
idev
->
close
=
cap11
xx
_input_close
;
input_set_drvdata
(
priv
->
idev
,
priv
);
input_set_drvdata
(
priv
->
idev
,
priv
);
...
@@ -291,7 +322,7 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,
...
@@ -291,7 +322,7 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,
* Put the device in deep sleep mode for now.
* Put the device in deep sleep mode for now.
* ->open() will bring it back once the it is actually needed.
* ->open() will bring it back once the it is actually needed.
*/
*/
cap11
06
_set_sleep
(
priv
,
true
);
cap11
xx
_set_sleep
(
priv
,
true
);
error
=
input_register_device
(
priv
->
idev
);
error
=
input_register_device
(
priv
->
idev
);
if
(
error
)
if
(
error
)
...
@@ -303,7 +334,7 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,
...
@@ -303,7 +334,7 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,
return
-
ENXIO
;
return
-
ENXIO
;
}
}
error
=
devm_request_threaded_irq
(
dev
,
irq
,
NULL
,
cap11
06
_thread_func
,
error
=
devm_request_threaded_irq
(
dev
,
irq
,
NULL
,
cap11
xx
_thread_func
,
IRQF_ONESHOT
,
dev_name
(
dev
),
priv
);
IRQF_ONESHOT
,
dev_name
(
dev
),
priv
);
if
(
error
)
if
(
error
)
return
error
;
return
error
;
...
@@ -311,31 +342,35 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,
...
@@ -311,31 +342,35 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,
return
0
;
return
0
;
}
}
static
const
struct
of_device_id
cap11
06
_dt_ids
[]
=
{
static
const
struct
of_device_id
cap11
xx
_dt_ids
[]
=
{
{
.
compatible
=
"microchip,cap1106"
,
},
{
.
compatible
=
"microchip,cap1106"
,
},
{
.
compatible
=
"microchip,cap1126"
,
},
{
.
compatible
=
"microchip,cap1188"
,
},
{}
{}
};
};
MODULE_DEVICE_TABLE
(
of
,
cap11
06
_dt_ids
);
MODULE_DEVICE_TABLE
(
of
,
cap11
xx
_dt_ids
);
static
const
struct
i2c_device_id
cap1106_i2c_ids
[]
=
{
static
const
struct
i2c_device_id
cap11xx_i2c_ids
[]
=
{
{
"cap1106"
,
0
},
{
"cap1106"
,
CAP1106
},
{
"cap1126"
,
CAP1126
},
{
"cap1188"
,
CAP1188
},
{}
{}
};
};
MODULE_DEVICE_TABLE
(
i2c
,
cap11
06
_i2c_ids
);
MODULE_DEVICE_TABLE
(
i2c
,
cap11
xx
_i2c_ids
);
static
struct
i2c_driver
cap11
06
_i2c_driver
=
{
static
struct
i2c_driver
cap11
xx
_i2c_driver
=
{
.
driver
=
{
.
driver
=
{
.
name
=
"cap11
06
"
,
.
name
=
"cap11
xx
"
,
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
of_match_table
=
cap11
06
_dt_ids
,
.
of_match_table
=
cap11
xx
_dt_ids
,
},
},
.
id_table
=
cap11
06
_i2c_ids
,
.
id_table
=
cap11
xx
_i2c_ids
,
.
probe
=
cap11
06
_i2c_probe
,
.
probe
=
cap11
xx
_i2c_probe
,
};
};
module_i2c_driver
(
cap11
06
_i2c_driver
);
module_i2c_driver
(
cap11
xx
_i2c_driver
);
MODULE_ALIAS
(
"platform:cap11
06
"
);
MODULE_ALIAS
(
"platform:cap11
xx
"
);
MODULE_DESCRIPTION
(
"Microchip CAP11
06
driver"
);
MODULE_DESCRIPTION
(
"Microchip CAP11
XX
driver"
);
MODULE_AUTHOR
(
"Daniel Mack <linux@zonque.org>"
);
MODULE_AUTHOR
(
"Daniel Mack <linux@zonque.org>"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_LICENSE
(
"GPL v2"
);
drivers/input/keyboard/gpio_keys.c
浏览文件 @
f20c86cd
...
@@ -29,6 +29,7 @@
...
@@ -29,6 +29,7 @@
#include <linux/of.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/spinlock.h>
#include <linux/spinlock.h>
struct
gpio_button_data
{
struct
gpio_button_data
{
...
@@ -617,27 +618,31 @@ gpio_keys_get_devtree_pdata(struct device *dev)
...
@@ -617,27 +618,31 @@ gpio_keys_get_devtree_pdata(struct device *dev)
i
=
0
;
i
=
0
;
for_each_child_of_node
(
node
,
pp
)
{
for_each_child_of_node
(
node
,
pp
)
{
int
gpio
;
int
gpio
=
-
1
;
enum
of_gpio_flags
flags
;
enum
of_gpio_flags
flags
;
if
(
!
of_find_property
(
pp
,
"gpios"
,
NULL
))
{
button
=
&
pdata
->
buttons
[
i
++
];
pdata
->
nbuttons
--
;
dev_warn
(
dev
,
"Found button without gpios
\n
"
);
continue
;
}
gpio
=
of_get_gpio_flags
(
pp
,
0
,
&
flags
);
if
(
!
of_find_property
(
pp
,
"gpios"
,
NULL
))
{
if
(
gpio
<
0
)
{
button
->
irq
=
irq_of_parse_and_map
(
pp
,
0
);
error
=
gpio
;
if
(
button
->
irq
==
0
)
{
if
(
error
!=
-
EPROBE_DEFER
)
i
--
;
dev_err
(
dev
,
pdata
->
nbuttons
--
;
"Failed to get gpio flags, error: %d
\n
"
,
dev_warn
(
dev
,
"Found button without gpios or irqs
\n
"
);
error
);
continue
;
return
ERR_PTR
(
error
);
}
}
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
=
&
pdata
->
buttons
[
i
++
];
button
->
gpio
=
gpio
;
button
->
gpio
=
gpio
;
button
->
active_low
=
flags
&
OF_GPIO_ACTIVE_LOW
;
button
->
active_low
=
flags
&
OF_GPIO_ACTIVE_LOW
;
...
...
drivers/input/keyboard/lm8323.c
浏览文件 @
f20c86cd
...
@@ -616,6 +616,8 @@ static ssize_t lm8323_set_disable(struct device *dev,
...
@@ -616,6 +616,8 @@ static ssize_t lm8323_set_disable(struct device *dev,
unsigned
int
i
;
unsigned
int
i
;
ret
=
kstrtouint
(
buf
,
10
,
&
i
);
ret
=
kstrtouint
(
buf
,
10
,
&
i
);
if
(
ret
)
return
ret
;
mutex_lock
(
&
lm
->
lock
);
mutex_lock
(
&
lm
->
lock
);
lm
->
kp_enabled
=
!
i
;
lm
->
kp_enabled
=
!
i
;
...
...
drivers/input/keyboard/lpc32xx-keys.c
浏览文件 @
f20c86cd
...
@@ -66,7 +66,6 @@
...
@@ -66,7 +66,6 @@
struct
lpc32xx_kscan_drv
{
struct
lpc32xx_kscan_drv
{
struct
input_dev
*
input
;
struct
input_dev
*
input
;
struct
clk
*
clk
;
struct
clk
*
clk
;
struct
resource
*
iores
;
void
__iomem
*
kscan_base
;
void
__iomem
*
kscan_base
;
unsigned
int
irq
;
unsigned
int
irq
;
...
@@ -188,32 +187,27 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev)
...
@@ -188,32 +187,27 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev)
return
-
EINVAL
;
return
-
EINVAL
;
}
}
kscandat
=
kzalloc
(
sizeof
(
struct
lpc32xx_kscan_drv
),
GFP_KERNEL
);
kscandat
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
kscandat
),
if
(
!
kscandat
)
{
GFP_KERNEL
);
dev_err
(
&
pdev
->
dev
,
"failed to allocate memory
\n
"
);
if
(
!
kscandat
)
return
-
ENOMEM
;
return
-
ENOMEM
;
}
error
=
lpc32xx_parse_dt
(
&
pdev
->
dev
,
kscandat
);
error
=
lpc32xx_parse_dt
(
&
pdev
->
dev
,
kscandat
);
if
(
error
)
{
if
(
error
)
{
dev_err
(
&
pdev
->
dev
,
"failed to parse device tree
\n
"
);
dev_err
(
&
pdev
->
dev
,
"failed to parse device tree
\n
"
);
goto
err_free_mem
;
return
error
;
}
}
keymap_size
=
sizeof
(
kscandat
->
keymap
[
0
])
*
keymap_size
=
sizeof
(
kscandat
->
keymap
[
0
])
*
(
kscandat
->
matrix_sz
<<
kscandat
->
row_shift
);
(
kscandat
->
matrix_sz
<<
kscandat
->
row_shift
);
kscandat
->
keymap
=
kzalloc
(
keymap_size
,
GFP_KERNEL
);
kscandat
->
keymap
=
devm_kzalloc
(
&
pdev
->
dev
,
keymap_size
,
GFP_KERNEL
);
if
(
!
kscandat
->
keymap
)
{
if
(
!
kscandat
->
keymap
)
dev_err
(
&
pdev
->
dev
,
"could not allocate memory for keymap
\n
"
);
return
-
ENOMEM
;
error
=
-
ENOMEM
;
goto
err_free_mem
;
}
kscandat
->
input
=
input
=
input_allocate_device
(
);
kscandat
->
input
=
input
=
devm_input_allocate_device
(
&
pdev
->
dev
);
if
(
!
input
)
{
if
(
!
input
)
{
dev_err
(
&
pdev
->
dev
,
"failed to allocate input device
\n
"
);
dev_err
(
&
pdev
->
dev
,
"failed to allocate input device
\n
"
);
error
=
-
ENOMEM
;
return
-
ENOMEM
;
goto
err_free_keymap
;
}
}
/* Setup key input */
/* Setup key input */
...
@@ -234,39 +228,26 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev)
...
@@ -234,39 +228,26 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev)
kscandat
->
keymap
,
kscandat
->
input
);
kscandat
->
keymap
,
kscandat
->
input
);
if
(
error
)
{
if
(
error
)
{
dev_err
(
&
pdev
->
dev
,
"failed to build keymap
\n
"
);
dev_err
(
&
pdev
->
dev
,
"failed to build keymap
\n
"
);
goto
err_free_input
;
return
error
;
}
}
input_set_drvdata
(
kscandat
->
input
,
kscandat
);
input_set_drvdata
(
kscandat
->
input
,
kscandat
);
kscandat
->
iores
=
request_mem_region
(
res
->
start
,
resource_size
(
res
),
kscandat
->
kscan_base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
pdev
->
name
);
if
(
IS_ERR
(
kscandat
->
kscan_base
))
if
(
!
kscandat
->
iores
)
{
return
PTR_ERR
(
kscandat
->
kscan_base
);
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
;
}
/* Get the key scanner clock */
/* 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
))
{
if
(
IS_ERR
(
kscandat
->
clk
))
{
dev_err
(
&
pdev
->
dev
,
"failed to get clock
\n
"
);
dev_err
(
&
pdev
->
dev
,
"failed to get clock
\n
"
);
error
=
PTR_ERR
(
kscandat
->
clk
);
return
PTR_ERR
(
kscandat
->
clk
);
goto
err_unmap
;
}
}
/* Configure the key scanner */
/* Configure the key scanner */
error
=
clk_prepare_enable
(
kscandat
->
clk
);
error
=
clk_prepare_enable
(
kscandat
->
clk
);
if
(
error
)
if
(
error
)
goto
err_clk_put
;
return
error
;
writel
(
kscandat
->
deb_clks
,
LPC32XX_KS_DEB
(
kscandat
->
kscan_base
));
writel
(
kscandat
->
deb_clks
,
LPC32XX_KS_DEB
(
kscandat
->
kscan_base
));
writel
(
kscandat
->
scan_delay
,
LPC32XX_KS_SCAN_CTL
(
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)
...
@@ -277,52 +258,20 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev)
writel
(
1
,
LPC32XX_KS_IRQ
(
kscandat
->
kscan_base
));
writel
(
1
,
LPC32XX_KS_IRQ
(
kscandat
->
kscan_base
));
clk_disable_unprepare
(
kscandat
->
clk
);
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
)
{
if
(
error
)
{
dev_err
(
&
pdev
->
dev
,
"failed to request irq
\n
"
);
dev_err
(
&
pdev
->
dev
,
"failed to request irq
\n
"
);
goto
err_clk_put
;
return
error
;
}
}
error
=
input_register_device
(
kscandat
->
input
);
error
=
input_register_device
(
kscandat
->
input
);
if
(
error
)
{
if
(
error
)
{
dev_err
(
&
pdev
->
dev
,
"failed to register input device
\n
"
);
dev_err
(
&
pdev
->
dev
,
"failed to register input device
\n
"
);
goto
err_free_irq
;
return
error
;
}
}
platform_set_drvdata
(
pdev
,
kscandat
);
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
;
return
0
;
}
}
...
@@ -378,7 +327,6 @@ MODULE_DEVICE_TABLE(of, lpc32xx_kscan_match);
...
@@ -378,7 +327,6 @@ MODULE_DEVICE_TABLE(of, lpc32xx_kscan_match);
static
struct
platform_driver
lpc32xx_kscan_driver
=
{
static
struct
platform_driver
lpc32xx_kscan_driver
=
{
.
probe
=
lpc32xx_kscan_probe
,
.
probe
=
lpc32xx_kscan_probe
,
.
remove
=
lpc32xx_kscan_remove
,
.
driver
=
{
.
driver
=
{
.
name
=
DRV_NAME
,
.
name
=
DRV_NAME
,
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
...
...
drivers/input/keyboard/mpr121_touchkey.c
浏览文件 @
f20c86cd
...
@@ -214,13 +214,14 @@ static int mpr_touchkey_probe(struct i2c_client *client,
...
@@ -214,13 +214,14 @@ static int mpr_touchkey_probe(struct i2c_client *client,
return
-
EINVAL
;
return
-
EINVAL
;
}
}
mpr121
=
kzalloc
(
sizeof
(
struct
mpr121_touchkey
),
GFP_KERNEL
);
mpr121
=
devm_kzalloc
(
&
client
->
dev
,
sizeof
(
*
mpr121
),
input_dev
=
input_allocate_device
();
GFP_KERNEL
);
if
(
!
mpr121
||
!
input_dev
)
{
if
(
!
mpr121
)
dev_err
(
&
client
->
dev
,
"Failed to allocate memory
\n
"
);
return
-
ENOMEM
;
error
=
-
ENOMEM
;
goto
err_free_mem
;
input_dev
=
devm_input_allocate_device
(
&
client
->
dev
);
}
if
(
!
input_dev
)
return
-
ENOMEM
;
mpr121
->
client
=
client
;
mpr121
->
client
=
client
;
mpr121
->
input_dev
=
input_dev
;
mpr121
->
input_dev
=
input_dev
;
...
@@ -243,43 +244,25 @@ static int mpr_touchkey_probe(struct i2c_client *client,
...
@@ -243,43 +244,25 @@ static int mpr_touchkey_probe(struct i2c_client *client,
error
=
mpr121_phys_init
(
pdata
,
mpr121
,
client
);
error
=
mpr121_phys_init
(
pdata
,
mpr121
,
client
);
if
(
error
)
{
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"Failed to init register
\n
"
);
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
,
mpr_touchkey_interrupt
,
IRQF_TRIGGER_FALLING
|
IRQF_ONESHOT
,
IRQF_TRIGGER_FALLING
|
IRQF_ONESHOT
,
client
->
dev
.
driver
->
name
,
mpr121
);
client
->
dev
.
driver
->
name
,
mpr121
);
if
(
error
)
{
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"Failed to register interrupt
\n
"
);
dev_err
(
&
client
->
dev
,
"Failed to register interrupt
\n
"
);
goto
err_free_mem
;
return
error
;
}
}
error
=
input_register_device
(
input_dev
);
error
=
input_register_device
(
input_dev
);
if
(
error
)
if
(
error
)
goto
err_free_irq
;
return
error
;
i2c_set_clientdata
(
client
,
mpr121
);
i2c_set_clientdata
(
client
,
mpr121
);
device_init_wakeup
(
&
client
->
dev
,
pdata
->
wakeup
);
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
;
return
0
;
}
}
...
@@ -327,7 +310,6 @@ static struct i2c_driver mpr_touchkey_driver = {
...
@@ -327,7 +310,6 @@ static struct i2c_driver mpr_touchkey_driver = {
},
},
.
id_table
=
mpr121_id
,
.
id_table
=
mpr121_id
,
.
probe
=
mpr_touchkey_probe
,
.
probe
=
mpr_touchkey_probe
,
.
remove
=
mpr_touchkey_remove
,
};
};
module_i2c_driver
(
mpr_touchkey_driver
);
module_i2c_driver
(
mpr_touchkey_driver
);
...
...
drivers/input/keyboard/pxa27x_keypad.c
浏览文件 @
f20c86cd
...
@@ -741,37 +741,27 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
...
@@ -741,37 +741,27 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
return
-
ENXIO
;
return
-
ENXIO
;
}
}
keypad
=
kzalloc
(
sizeof
(
struct
pxa27x_keypad
),
GFP_KERNEL
);
keypad
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
keypad
),
input_dev
=
input_allocate_device
();
GFP_KERNEL
);
if
(
!
keypad
||
!
input_dev
)
{
if
(
!
keypad
)
dev_err
(
&
pdev
->
dev
,
"failed to allocate memory
\n
"
);
return
-
ENOMEM
;
error
=
-
ENOMEM
;
goto
failed_free
;
input_dev
=
devm_input_allocate_device
(
&
pdev
->
dev
);
}
if
(
!
input_dev
)
return
-
ENOMEM
;
keypad
->
pdata
=
pdata
;
keypad
->
pdata
=
pdata
;
keypad
->
input_dev
=
input_dev
;
keypad
->
input_dev
=
input_dev
;
keypad
->
irq
=
irq
;
keypad
->
irq
=
irq
;
res
=
request_mem_region
(
res
->
start
,
resource_size
(
res
),
pdev
->
name
);
keypad
->
mmio_base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
res
==
NULL
)
{
if
(
IS_ERR
(
keypad
->
mmio_base
))
dev_err
(
&
pdev
->
dev
,
"failed to request I/O memory
\n
"
);
return
PTR_ERR
(
keypad
->
mmio_base
);
error
=
-
EBUSY
;
goto
failed_free
;
}
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
))
{
if
(
IS_ERR
(
keypad
->
clk
))
{
dev_err
(
&
pdev
->
dev
,
"failed to get keypad clock
\n
"
);
dev_err
(
&
pdev
->
dev
,
"failed to get keypad clock
\n
"
);
error
=
PTR_ERR
(
keypad
->
clk
);
return
PTR_ERR
(
keypad
->
clk
);
goto
failed_free_io
;
}
}
input_dev
->
name
=
pdev
->
name
;
input_dev
->
name
=
pdev
->
name
;
...
@@ -802,7 +792,7 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
...
@@ -802,7 +792,7 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
}
}
if
(
error
)
{
if
(
error
)
{
dev_err
(
&
pdev
->
dev
,
"failed to build keycode
\n
"
);
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
);
keypad
->
row_shift
=
get_count_order
(
pdata
->
matrix_key_cols
);
...
@@ -812,61 +802,26 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
...
@@ -812,61 +802,26 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
input_dev
->
evbit
[
0
]
|=
BIT_MASK
(
EV_REL
);
input_dev
->
evbit
[
0
]
|=
BIT_MASK
(
EV_REL
);
}
}
error
=
request_irq
(
irq
,
pxa27x_keypad_irq_handler
,
0
,
error
=
devm_request_irq
(
&
pdev
->
dev
,
irq
,
pxa27x_keypad_irq_handler
,
pdev
->
name
,
keypad
);
0
,
pdev
->
name
,
keypad
);
if
(
error
)
{
if
(
error
)
{
dev_err
(
&
pdev
->
dev
,
"failed to request IRQ
\n
"
);
dev_err
(
&
pdev
->
dev
,
"failed to request IRQ
\n
"
);
goto
failed_put_clk
;
return
error
;
}
}
/* Register the input device */
/* Register the input device */
error
=
input_register_device
(
input_dev
);
error
=
input_register_device
(
input_dev
);
if
(
error
)
{
if
(
error
)
{
dev_err
(
&
pdev
->
dev
,
"failed to register input device
\n
"
);
dev_err
(
&
pdev
->
dev
,
"failed to register input device
\n
"
);
goto
failed_free_irq
;
return
error
;
}
}
platform_set_drvdata
(
pdev
,
keypad
);
platform_set_drvdata
(
pdev
,
keypad
);
device_init_wakeup
(
&
pdev
->
dev
,
1
);
device_init_wakeup
(
&
pdev
->
dev
,
1
);
return
0
;
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
#ifdef CONFIG_OF
static
const
struct
of_device_id
pxa27x_keypad_dt_match
[]
=
{
static
const
struct
of_device_id
pxa27x_keypad_dt_match
[]
=
{
{
.
compatible
=
"marvell,pxa27x-keypad"
},
{
.
compatible
=
"marvell,pxa27x-keypad"
},
...
@@ -877,7 +832,6 @@ MODULE_DEVICE_TABLE(of, pxa27x_keypad_dt_match);
...
@@ -877,7 +832,6 @@ MODULE_DEVICE_TABLE(of, pxa27x_keypad_dt_match);
static
struct
platform_driver
pxa27x_keypad_driver
=
{
static
struct
platform_driver
pxa27x_keypad_driver
=
{
.
probe
=
pxa27x_keypad_probe
,
.
probe
=
pxa27x_keypad_probe
,
.
remove
=
pxa27x_keypad_remove
,
.
driver
=
{
.
driver
=
{
.
name
=
"pxa27x-keypad"
,
.
name
=
"pxa27x-keypad"
,
.
of_match_table
=
of_match_ptr
(
pxa27x_keypad_dt_match
),
.
of_match_table
=
of_match_ptr
(
pxa27x_keypad_dt_match
),
...
@@ -889,3 +843,5 @@ module_platform_driver(pxa27x_keypad_driver);
...
@@ -889,3 +843,5 @@ module_platform_driver(pxa27x_keypad_driver);
MODULE_DESCRIPTION
(
"PXA27x Keypad Controller Driver"
);
MODULE_DESCRIPTION
(
"PXA27x Keypad Controller Driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
/* work with hotplug and coldplug */
MODULE_ALIAS
(
"platform:pxa27x-keypad"
);
drivers/input/misc/88pm860x_onkey.c
浏览文件 @
f20c86cd
...
@@ -112,8 +112,7 @@ static int pm860x_onkey_probe(struct platform_device *pdev)
...
@@ -112,8 +112,7 @@ static int pm860x_onkey_probe(struct platform_device *pdev)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
pm860x_onkey_suspend
(
struct
device
*
dev
)
static
int
pm860x_onkey_suspend
(
struct
device
*
dev
)
{
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
pm860x_chip
*
chip
=
dev_get_drvdata
(
pdev
->
dev
.
parent
);
struct
pm860x_chip
*
chip
=
dev_get_drvdata
(
pdev
->
dev
.
parent
);
...
@@ -122,7 +121,7 @@ static int pm860x_onkey_suspend(struct device *dev)
...
@@ -122,7 +121,7 @@ static int pm860x_onkey_suspend(struct device *dev)
chip
->
wakeup_flag
|=
1
<<
PM8607_IRQ_ONKEY
;
chip
->
wakeup_flag
|=
1
<<
PM8607_IRQ_ONKEY
;
return
0
;
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
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
pm860x_chip
*
chip
=
dev_get_drvdata
(
pdev
->
dev
.
parent
);
struct
pm860x_chip
*
chip
=
dev_get_drvdata
(
pdev
->
dev
.
parent
);
...
@@ -131,7 +130,6 @@ static int pm860x_onkey_resume(struct device *dev)
...
@@ -131,7 +130,6 @@ static int pm860x_onkey_resume(struct device *dev)
chip
->
wakeup_flag
&=
~
(
1
<<
PM8607_IRQ_ONKEY
);
chip
->
wakeup_flag
&=
~
(
1
<<
PM8607_IRQ_ONKEY
);
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
pm860x_onkey_pm_ops
,
pm860x_onkey_suspend
,
pm860x_onkey_resume
);
static
SIMPLE_DEV_PM_OPS
(
pm860x_onkey_pm_ops
,
pm860x_onkey_suspend
,
pm860x_onkey_resume
);
...
...
drivers/input/misc/ad714x-i2c.c
浏览文件 @
f20c86cd
...
@@ -13,17 +13,15 @@
...
@@ -13,17 +13,15 @@
#include <linux/pm.h>
#include <linux/pm.h>
#include "ad714x.h"
#include "ad714x.h"
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
ad714x_i2c_suspend
(
struct
device
*
dev
)
static
int
ad714x_i2c_suspend
(
struct
device
*
dev
)
{
{
return
ad714x_disable
(
i2c_get_clientdata
(
to_i2c_client
(
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
)));
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
);
static
SIMPLE_DEV_PM_OPS
(
ad714x_i2c_pm
,
ad714x_i2c_suspend
,
ad714x_i2c_resume
);
...
...
drivers/input/misc/ad714x-spi.c
浏览文件 @
f20c86cd
...
@@ -16,17 +16,15 @@
...
@@ -16,17 +16,15 @@
#define AD714x_SPI_CMD_PREFIX 0xE000
/* bits 15:11 */
#define AD714x_SPI_CMD_PREFIX 0xE000
/* bits 15:11 */
#define AD714x_SPI_READ BIT(10)
#define AD714x_SPI_READ BIT(10)
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
ad714x_spi_suspend
(
struct
device
*
dev
)
static
int
ad714x_spi_suspend
(
struct
device
*
dev
)
{
{
return
ad714x_disable
(
spi_get_drvdata
(
to_spi_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
)));
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
);
static
SIMPLE_DEV_PM_OPS
(
ad714x_spi_pm
,
ad714x_spi_suspend
,
ad714x_spi_resume
);
...
...
drivers/input/misc/adxl34x-i2c.c
浏览文件 @
f20c86cd
...
@@ -105,8 +105,7 @@ static int adxl34x_i2c_remove(struct i2c_client *client)
...
@@ -105,8 +105,7 @@ static int adxl34x_i2c_remove(struct i2c_client *client)
return
adxl34x_remove
(
ac
);
return
adxl34x_remove
(
ac
);
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
adxl34x_i2c_suspend
(
struct
device
*
dev
)
static
int
adxl34x_i2c_suspend
(
struct
device
*
dev
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
adxl34x
*
ac
=
i2c_get_clientdata
(
client
);
struct
adxl34x
*
ac
=
i2c_get_clientdata
(
client
);
...
@@ -116,7 +115,7 @@ static int adxl34x_i2c_suspend(struct device *dev)
...
@@ -116,7 +115,7 @@ static int adxl34x_i2c_suspend(struct device *dev)
return
0
;
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
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
adxl34x
*
ac
=
i2c_get_clientdata
(
client
);
struct
adxl34x
*
ac
=
i2c_get_clientdata
(
client
);
...
@@ -125,7 +124,6 @@ static int adxl34x_i2c_resume(struct device *dev)
...
@@ -125,7 +124,6 @@ static int adxl34x_i2c_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
adxl34x_i2c_pm
,
adxl34x_i2c_suspend
,
static
SIMPLE_DEV_PM_OPS
(
adxl34x_i2c_pm
,
adxl34x_i2c_suspend
,
adxl34x_i2c_resume
);
adxl34x_i2c_resume
);
...
...
drivers/input/misc/adxl34x-spi.c
浏览文件 @
f20c86cd
...
@@ -94,8 +94,7 @@ static int adxl34x_spi_remove(struct spi_device *spi)
...
@@ -94,8 +94,7 @@ static int adxl34x_spi_remove(struct spi_device *spi)
return
adxl34x_remove
(
ac
);
return
adxl34x_remove
(
ac
);
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
adxl34x_spi_suspend
(
struct
device
*
dev
)
static
int
adxl34x_spi_suspend
(
struct
device
*
dev
)
{
{
struct
spi_device
*
spi
=
to_spi_device
(
dev
);
struct
spi_device
*
spi
=
to_spi_device
(
dev
);
struct
adxl34x
*
ac
=
spi_get_drvdata
(
spi
);
struct
adxl34x
*
ac
=
spi_get_drvdata
(
spi
);
...
@@ -105,7 +104,7 @@ static int adxl34x_spi_suspend(struct device *dev)
...
@@ -105,7 +104,7 @@ static int adxl34x_spi_suspend(struct device *dev)
return
0
;
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
spi_device
*
spi
=
to_spi_device
(
dev
);
struct
adxl34x
*
ac
=
spi_get_drvdata
(
spi
);
struct
adxl34x
*
ac
=
spi_get_drvdata
(
spi
);
...
@@ -114,7 +113,6 @@ static int adxl34x_spi_resume(struct device *dev)
...
@@ -114,7 +113,6 @@ static int adxl34x_spi_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
adxl34x_spi_pm
,
adxl34x_spi_suspend
,
static
SIMPLE_DEV_PM_OPS
(
adxl34x_spi_pm
,
adxl34x_spi_suspend
,
adxl34x_spi_resume
);
adxl34x_spi_resume
);
...
...
drivers/input/misc/drv260x.c
浏览文件 @
f20c86cd
...
@@ -639,8 +639,7 @@ static int drv260x_probe(struct i2c_client *client,
...
@@ -639,8 +639,7 @@ static int drv260x_probe(struct i2c_client *client,
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
drv260x_suspend
(
struct
device
*
dev
)
static
int
drv260x_suspend
(
struct
device
*
dev
)
{
{
struct
drv260x_data
*
haptics
=
dev_get_drvdata
(
dev
);
struct
drv260x_data
*
haptics
=
dev_get_drvdata
(
dev
);
int
ret
=
0
;
int
ret
=
0
;
...
@@ -672,7 +671,7 @@ static int drv260x_suspend(struct device *dev)
...
@@ -672,7 +671,7 @@ static int drv260x_suspend(struct device *dev)
return
ret
;
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
);
struct
drv260x_data
*
haptics
=
dev_get_drvdata
(
dev
);
int
ret
=
0
;
int
ret
=
0
;
...
@@ -702,7 +701,6 @@ static int drv260x_resume(struct device *dev)
...
@@ -702,7 +701,6 @@ static int drv260x_resume(struct device *dev)
mutex_unlock
(
&
haptics
->
input_dev
->
mutex
);
mutex_unlock
(
&
haptics
->
input_dev
->
mutex
);
return
ret
;
return
ret
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
drv260x_pm_ops
,
drv260x_suspend
,
drv260x_resume
);
static
SIMPLE_DEV_PM_OPS
(
drv260x_pm_ops
,
drv260x_suspend
,
drv260x_resume
);
...
...
drivers/input/misc/drv2667.c
浏览文件 @
f20c86cd
...
@@ -406,8 +406,7 @@ static int drv2667_probe(struct i2c_client *client,
...
@@ -406,8 +406,7 @@ static int drv2667_probe(struct i2c_client *client,
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
drv2667_suspend
(
struct
device
*
dev
)
static
int
drv2667_suspend
(
struct
device
*
dev
)
{
{
struct
drv2667_data
*
haptics
=
dev_get_drvdata
(
dev
);
struct
drv2667_data
*
haptics
=
dev_get_drvdata
(
dev
);
int
ret
=
0
;
int
ret
=
0
;
...
@@ -436,7 +435,7 @@ static int drv2667_suspend(struct device *dev)
...
@@ -436,7 +435,7 @@ static int drv2667_suspend(struct device *dev)
return
ret
;
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
);
struct
drv2667_data
*
haptics
=
dev_get_drvdata
(
dev
);
int
ret
=
0
;
int
ret
=
0
;
...
@@ -464,7 +463,6 @@ static int drv2667_resume(struct device *dev)
...
@@ -464,7 +463,6 @@ static int drv2667_resume(struct device *dev)
mutex_unlock
(
&
haptics
->
input_dev
->
mutex
);
mutex_unlock
(
&
haptics
->
input_dev
->
mutex
);
return
ret
;
return
ret
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
drv2667_pm_ops
,
drv2667_suspend
,
drv2667_resume
);
static
SIMPLE_DEV_PM_OPS
(
drv2667_pm_ops
,
drv2667_suspend
,
drv2667_resume
);
...
...
drivers/input/misc/gp2ap002a00f.c
浏览文件 @
f20c86cd
...
@@ -225,8 +225,7 @@ static int gp2a_remove(struct i2c_client *client)
...
@@ -225,8 +225,7 @@ static int gp2a_remove(struct i2c_client *client)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
gp2a_suspend
(
struct
device
*
dev
)
static
int
gp2a_suspend
(
struct
device
*
dev
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
gp2a_data
*
dt
=
i2c_get_clientdata
(
client
);
struct
gp2a_data
*
dt
=
i2c_get_clientdata
(
client
);
...
@@ -244,7 +243,7 @@ static int gp2a_suspend(struct device *dev)
...
@@ -244,7 +243,7 @@ static int gp2a_suspend(struct device *dev)
return
retval
;
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
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
gp2a_data
*
dt
=
i2c_get_clientdata
(
client
);
struct
gp2a_data
*
dt
=
i2c_get_clientdata
(
client
);
...
@@ -261,7 +260,6 @@ static int gp2a_resume(struct device *dev)
...
@@ -261,7 +260,6 @@ static int gp2a_resume(struct device *dev)
return
retval
;
return
retval
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
gp2a_pm
,
gp2a_suspend
,
gp2a_resume
);
static
SIMPLE_DEV_PM_OPS
(
gp2a_pm
,
gp2a_suspend
,
gp2a_resume
);
...
...
drivers/input/misc/ims-pcu.c
浏览文件 @
f20c86cd
...
@@ -1851,7 +1851,7 @@ static int ims_pcu_identify_type(struct ims_pcu *pcu, u8 *device_id)
...
@@ -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
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
;
const
struct
ims_pcu_device_info
*
info
;
int
error
;
int
error
;
...
@@ -1882,7 +1882,7 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)
...
@@ -1882,7 +1882,7 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)
}
}
/* Device appears to be operable, complete initialization */
/* 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
* PCU-B devices, both GEN_1 and GEN_2 do not have OFN sensor
...
...
drivers/input/misc/kxtj9.c
浏览文件 @
f20c86cd
...
@@ -615,8 +615,7 @@ static int kxtj9_remove(struct i2c_client *client)
...
@@ -615,8 +615,7 @@ static int kxtj9_remove(struct i2c_client *client)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
kxtj9_suspend
(
struct
device
*
dev
)
static
int
kxtj9_suspend
(
struct
device
*
dev
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
kxtj9_data
*
tj9
=
i2c_get_clientdata
(
client
);
struct
kxtj9_data
*
tj9
=
i2c_get_clientdata
(
client
);
...
@@ -631,7 +630,7 @@ static int kxtj9_suspend(struct device *dev)
...
@@ -631,7 +630,7 @@ static int kxtj9_suspend(struct device *dev)
return
0
;
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
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
kxtj9_data
*
tj9
=
i2c_get_clientdata
(
client
);
struct
kxtj9_data
*
tj9
=
i2c_get_clientdata
(
client
);
...
@@ -646,7 +645,6 @@ static int kxtj9_resume(struct device *dev)
...
@@ -646,7 +645,6 @@ static int kxtj9_resume(struct device *dev)
mutex_unlock
(
&
input_dev
->
mutex
);
mutex_unlock
(
&
input_dev
->
mutex
);
return
retval
;
return
retval
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
kxtj9_pm_ops
,
kxtj9_suspend
,
kxtj9_resume
);
static
SIMPLE_DEV_PM_OPS
(
kxtj9_pm_ops
,
kxtj9_suspend
,
kxtj9_resume
);
...
...
drivers/input/misc/max77693-haptic.c
浏览文件 @
f20c86cd
...
@@ -309,8 +309,7 @@ static int max77693_haptic_probe(struct platform_device *pdev)
...
@@ -309,8 +309,7 @@ static int max77693_haptic_probe(struct platform_device *pdev)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
max77693_haptic_suspend
(
struct
device
*
dev
)
static
int
max77693_haptic_suspend
(
struct
device
*
dev
)
{
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
max77693_haptic
*
haptic
=
platform_get_drvdata
(
pdev
);
struct
max77693_haptic
*
haptic
=
platform_get_drvdata
(
pdev
);
...
@@ -323,7 +322,7 @@ static int max77693_haptic_suspend(struct device *dev)
...
@@ -323,7 +322,7 @@ static int max77693_haptic_suspend(struct device *dev)
return
0
;
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
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
max77693_haptic
*
haptic
=
platform_get_drvdata
(
pdev
);
struct
max77693_haptic
*
haptic
=
platform_get_drvdata
(
pdev
);
...
@@ -335,7 +334,6 @@ static int max77693_haptic_resume(struct device *dev)
...
@@ -335,7 +334,6 @@ static int max77693_haptic_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
max77693_haptic_pm_ops
,
static
SIMPLE_DEV_PM_OPS
(
max77693_haptic_pm_ops
,
max77693_haptic_suspend
,
max77693_haptic_resume
);
max77693_haptic_suspend
,
max77693_haptic_resume
);
...
...
drivers/input/misc/max8925_onkey.c
浏览文件 @
f20c86cd
...
@@ -133,8 +133,7 @@ static int max8925_onkey_probe(struct platform_device *pdev)
...
@@ -133,8 +133,7 @@ static int max8925_onkey_probe(struct platform_device *pdev)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
max8925_onkey_suspend
(
struct
device
*
dev
)
static
int
max8925_onkey_suspend
(
struct
device
*
dev
)
{
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
max8925_onkey_info
*
info
=
platform_get_drvdata
(
pdev
);
struct
max8925_onkey_info
*
info
=
platform_get_drvdata
(
pdev
);
...
@@ -148,7 +147,7 @@ static int max8925_onkey_suspend(struct device *dev)
...
@@ -148,7 +147,7 @@ static int max8925_onkey_suspend(struct device *dev)
return
0
;
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
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
max8925_onkey_info
*
info
=
platform_get_drvdata
(
pdev
);
struct
max8925_onkey_info
*
info
=
platform_get_drvdata
(
pdev
);
...
@@ -161,7 +160,6 @@ static int max8925_onkey_resume(struct device *dev)
...
@@ -161,7 +160,6 @@ static int max8925_onkey_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
max8925_onkey_pm_ops
,
max8925_onkey_suspend
,
max8925_onkey_resume
);
static
SIMPLE_DEV_PM_OPS
(
max8925_onkey_pm_ops
,
max8925_onkey_suspend
,
max8925_onkey_resume
);
...
...
drivers/input/misc/max8997_haptic.c
浏览文件 @
f20c86cd
...
@@ -378,8 +378,7 @@ static int max8997_haptic_remove(struct platform_device *pdev)
...
@@ -378,8 +378,7 @@ static int max8997_haptic_remove(struct platform_device *pdev)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
max8997_haptic_suspend
(
struct
device
*
dev
)
static
int
max8997_haptic_suspend
(
struct
device
*
dev
)
{
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
max8997_haptic
*
chip
=
platform_get_drvdata
(
pdev
);
struct
max8997_haptic
*
chip
=
platform_get_drvdata
(
pdev
);
...
@@ -388,7 +387,6 @@ static int max8997_haptic_suspend(struct device *dev)
...
@@ -388,7 +387,6 @@ static int max8997_haptic_suspend(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
max8997_haptic_pm_ops
,
max8997_haptic_suspend
,
NULL
);
static
SIMPLE_DEV_PM_OPS
(
max8997_haptic_pm_ops
,
max8997_haptic_suspend
,
NULL
);
...
...
drivers/input/misc/palmas-pwrbutton.c
浏览文件 @
f20c86cd
...
@@ -260,7 +260,6 @@ static int palmas_pwron_remove(struct platform_device *pdev)
...
@@ -260,7 +260,6 @@ static int palmas_pwron_remove(struct platform_device *pdev)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
/**
/**
* palmas_pwron_suspend() - suspend handler
* palmas_pwron_suspend() - suspend handler
* @dev: power button device
* @dev: power button device
...
@@ -269,7 +268,7 @@ static int palmas_pwron_remove(struct platform_device *pdev)
...
@@ -269,7 +268,7 @@ static int palmas_pwron_remove(struct platform_device *pdev)
*
*
* Return: 0
* 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
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
palmas_pwron
*
pwron
=
platform_get_drvdata
(
pdev
);
struct
palmas_pwron
*
pwron
=
platform_get_drvdata
(
pdev
);
...
@@ -290,7 +289,7 @@ static int palmas_pwron_suspend(struct device *dev)
...
@@ -290,7 +289,7 @@ static int palmas_pwron_suspend(struct device *dev)
*
*
* Return: 0
* 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
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
palmas_pwron
*
pwron
=
platform_get_drvdata
(
pdev
);
struct
palmas_pwron
*
pwron
=
platform_get_drvdata
(
pdev
);
...
@@ -300,7 +299,6 @@ static int palmas_pwron_resume(struct device *dev)
...
@@ -300,7 +299,6 @@ static int palmas_pwron_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
palmas_pwron_pm
,
static
SIMPLE_DEV_PM_OPS
(
palmas_pwron_pm
,
palmas_pwron_suspend
,
palmas_pwron_resume
);
palmas_pwron_suspend
,
palmas_pwron_resume
);
...
...
drivers/input/misc/pm8xxx-vibrator.c
浏览文件 @
f20c86cd
...
@@ -199,8 +199,7 @@ static int pm8xxx_vib_probe(struct platform_device *pdev)
...
@@ -199,8 +199,7 @@ static int pm8xxx_vib_probe(struct platform_device *pdev)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
pm8xxx_vib_suspend
(
struct
device
*
dev
)
static
int
pm8xxx_vib_suspend
(
struct
device
*
dev
)
{
{
struct
pm8xxx_vib
*
vib
=
dev_get_drvdata
(
dev
);
struct
pm8xxx_vib
*
vib
=
dev_get_drvdata
(
dev
);
...
@@ -209,7 +208,6 @@ static int pm8xxx_vib_suspend(struct device *dev)
...
@@ -209,7 +208,6 @@ static int pm8xxx_vib_suspend(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
pm8xxx_vib_pm_ops
,
pm8xxx_vib_suspend
,
NULL
);
static
SIMPLE_DEV_PM_OPS
(
pm8xxx_vib_pm_ops
,
pm8xxx_vib_suspend
,
NULL
);
...
...
drivers/input/misc/pmic8xxx-pwrkey.c
浏览文件 @
f20c86cd
...
@@ -53,8 +53,7 @@ static irqreturn_t pwrkey_release_irq(int irq, void *_pwr)
...
@@ -53,8 +53,7 @@ static irqreturn_t pwrkey_release_irq(int irq, void *_pwr)
return
IRQ_HANDLED
;
return
IRQ_HANDLED
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
pmic8xxx_pwrkey_suspend
(
struct
device
*
dev
)
static
int
pmic8xxx_pwrkey_suspend
(
struct
device
*
dev
)
{
{
struct
pmic8xxx_pwrkey
*
pwrkey
=
dev_get_drvdata
(
dev
);
struct
pmic8xxx_pwrkey
*
pwrkey
=
dev_get_drvdata
(
dev
);
...
@@ -64,7 +63,7 @@ static int pmic8xxx_pwrkey_suspend(struct device *dev)
...
@@ -64,7 +63,7 @@ static int pmic8xxx_pwrkey_suspend(struct device *dev)
return
0
;
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
);
struct
pmic8xxx_pwrkey
*
pwrkey
=
dev_get_drvdata
(
dev
);
...
@@ -73,7 +72,6 @@ static int pmic8xxx_pwrkey_resume(struct device *dev)
...
@@ -73,7 +72,6 @@ static int pmic8xxx_pwrkey_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
pm8xxx_pwr_key_pm_ops
,
static
SIMPLE_DEV_PM_OPS
(
pm8xxx_pwr_key_pm_ops
,
pmic8xxx_pwrkey_suspend
,
pmic8xxx_pwrkey_resume
);
pmic8xxx_pwrkey_suspend
,
pmic8xxx_pwrkey_resume
);
...
...
drivers/input/misc/pwm-beeper.c
浏览文件 @
f20c86cd
...
@@ -144,8 +144,7 @@ static int pwm_beeper_remove(struct platform_device *pdev)
...
@@ -144,8 +144,7 @@ static int pwm_beeper_remove(struct platform_device *pdev)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
pwm_beeper_suspend
(
struct
device
*
dev
)
static
int
pwm_beeper_suspend
(
struct
device
*
dev
)
{
{
struct
pwm_beeper
*
beeper
=
dev_get_drvdata
(
dev
);
struct
pwm_beeper
*
beeper
=
dev_get_drvdata
(
dev
);
...
@@ -155,7 +154,7 @@ static int pwm_beeper_suspend(struct device *dev)
...
@@ -155,7 +154,7 @@ static int pwm_beeper_suspend(struct device *dev)
return
0
;
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
);
struct
pwm_beeper
*
beeper
=
dev_get_drvdata
(
dev
);
...
@@ -170,6 +169,7 @@ static int pwm_beeper_resume(struct device *dev)
...
@@ -170,6 +169,7 @@ static int pwm_beeper_resume(struct device *dev)
static
SIMPLE_DEV_PM_OPS
(
pwm_beeper_pm_ops
,
static
SIMPLE_DEV_PM_OPS
(
pwm_beeper_pm_ops
,
pwm_beeper_suspend
,
pwm_beeper_resume
);
pwm_beeper_suspend
,
pwm_beeper_resume
);
#ifdef CONFIG_PM_SLEEP
#define PWM_BEEPER_PM_OPS (&pwm_beeper_pm_ops)
#define PWM_BEEPER_PM_OPS (&pwm_beeper_pm_ops)
#else
#else
#define PWM_BEEPER_PM_OPS NULL
#define PWM_BEEPER_PM_OPS NULL
...
...
drivers/input/misc/sirfsoc-onkey.c
浏览文件 @
f20c86cd
...
@@ -179,8 +179,7 @@ static int sirfsoc_pwrc_remove(struct platform_device *pdev)
...
@@ -179,8 +179,7 @@ static int sirfsoc_pwrc_remove(struct platform_device *pdev)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
sirfsoc_pwrc_resume
(
struct
device
*
dev
)
static
int
sirfsoc_pwrc_resume
(
struct
device
*
dev
)
{
{
struct
sirfsoc_pwrc_drvdata
*
pwrcdrv
=
dev_get_drvdata
(
dev
);
struct
sirfsoc_pwrc_drvdata
*
pwrcdrv
=
dev_get_drvdata
(
dev
);
struct
input_dev
*
input
=
pwrcdrv
->
input
;
struct
input_dev
*
input
=
pwrcdrv
->
input
;
...
@@ -196,7 +195,6 @@ static int sirfsoc_pwrc_resume(struct device *dev)
...
@@ -196,7 +195,6 @@ static int sirfsoc_pwrc_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
sirfsoc_pwrc_pm_ops
,
NULL
,
sirfsoc_pwrc_resume
);
static
SIMPLE_DEV_PM_OPS
(
sirfsoc_pwrc_pm_ops
,
NULL
,
sirfsoc_pwrc_resume
);
...
...
drivers/input/misc/twl4030-vibra.c
浏览文件 @
f20c86cd
...
@@ -157,8 +157,7 @@ static void twl4030_vibra_close(struct input_dev *input)
...
@@ -157,8 +157,7 @@ static void twl4030_vibra_close(struct input_dev *input)
}
}
/*** Module ***/
/*** Module ***/
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
twl4030_vibra_suspend
(
struct
device
*
dev
)
static
int
twl4030_vibra_suspend
(
struct
device
*
dev
)
{
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
vibra_info
*
info
=
platform_get_drvdata
(
pdev
);
struct
vibra_info
*
info
=
platform_get_drvdata
(
pdev
);
...
@@ -169,12 +168,11 @@ static int twl4030_vibra_suspend(struct device *dev)
...
@@ -169,12 +168,11 @@ static int twl4030_vibra_suspend(struct device *dev)
return
0
;
return
0
;
}
}
static
int
twl4030_vibra_resume
(
struct
device
*
dev
)
static
int
__maybe_unused
twl4030_vibra_resume
(
struct
device
*
dev
)
{
{
vibra_disable_leds
();
vibra_disable_leds
();
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
twl4030_vibra_pm_ops
,
static
SIMPLE_DEV_PM_OPS
(
twl4030_vibra_pm_ops
,
twl4030_vibra_suspend
,
twl4030_vibra_resume
);
twl4030_vibra_suspend
,
twl4030_vibra_resume
);
...
...
drivers/input/misc/twl6040-vibra.c
浏览文件 @
f20c86cd
...
@@ -236,8 +236,7 @@ static void twl6040_vibra_close(struct input_dev *input)
...
@@ -236,8 +236,7 @@ static void twl6040_vibra_close(struct input_dev *input)
mutex_unlock
(
&
info
->
mutex
);
mutex_unlock
(
&
info
->
mutex
);
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
twl6040_vibra_suspend
(
struct
device
*
dev
)
static
int
twl6040_vibra_suspend
(
struct
device
*
dev
)
{
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
vibra_info
*
info
=
platform_get_drvdata
(
pdev
);
struct
vibra_info
*
info
=
platform_get_drvdata
(
pdev
);
...
@@ -251,7 +250,6 @@ static int twl6040_vibra_suspend(struct device *dev)
...
@@ -251,7 +250,6 @@ static int twl6040_vibra_suspend(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
twl6040_vibra_pm_ops
,
twl6040_vibra_suspend
,
NULL
);
static
SIMPLE_DEV_PM_OPS
(
twl6040_vibra_pm_ops
,
twl6040_vibra_suspend
,
NULL
);
...
...
drivers/input/mouse/Kconfig
浏览文件 @
f20c86cd
...
@@ -215,6 +215,36 @@ config MOUSE_CYAPA
...
@@ -215,6 +215,36 @@ config MOUSE_CYAPA
To compile this driver as a module, choose M here: the module will be
To compile this driver as a module, choose M here: the module will be
called cyapa.
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
config MOUSE_INPORT
tristate "InPort/MS/ATIXL busmouse"
tristate "InPort/MS/ATIXL busmouse"
depends on ISA
depends on ISA
...
...
drivers/input/mouse/Makefile
浏览文件 @
f20c86cd
...
@@ -9,6 +9,7 @@ obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o
...
@@ -9,6 +9,7 @@ obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o
obj-$(CONFIG_MOUSE_ATARI)
+=
atarimouse.o
obj-$(CONFIG_MOUSE_ATARI)
+=
atarimouse.o
obj-$(CONFIG_MOUSE_BCM5974)
+=
bcm5974.o
obj-$(CONFIG_MOUSE_BCM5974)
+=
bcm5974.o
obj-$(CONFIG_MOUSE_CYAPA)
+=
cyapa.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_GPIO)
+=
gpio_mouse.o
obj-$(CONFIG_MOUSE_INPORT)
+=
inport.o
obj-$(CONFIG_MOUSE_INPORT)
+=
inport.o
obj-$(CONFIG_MOUSE_LOGIBM)
+=
logibm.o
obj-$(CONFIG_MOUSE_LOGIBM)
+=
logibm.o
...
@@ -34,3 +35,7 @@ psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o
...
@@ -34,3 +35,7 @@ psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o
psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT)
+=
trackpoint.o
psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT)
+=
trackpoint.o
psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT)
+=
touchkit_ps2.o
psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT)
+=
touchkit_ps2.o
psmouse-$(CONFIG_MOUSE_PS2_CYPRESS)
+=
cypress_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
drivers/input/mouse/cyapa.c
浏览文件 @
f20c86cd
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Daniel Kurtz <djkurtz@chromium.org>
* Daniel Kurtz <djkurtz@chromium.org>
* Benson Leung <bleung@chromium.org>
* Benson Leung <bleung@chromium.org>
*
*
* Copyright (C) 2011-201
2
Cypress Semiconductor, Inc.
* Copyright (C) 2011-201
4
Cypress Semiconductor, Inc.
* Copyright (C) 2011-2012 Google, Inc.
* Copyright (C) 2011-2012 Google, Inc.
*
*
* This file is subject to the terms and conditions of the GNU General Public
* This file is subject to the terms and conditions of the GNU General Public
...
@@ -206,7 +206,6 @@ struct cyapa {
...
@@ -206,7 +206,6 @@ struct cyapa {
struct
i2c_client
*
client
;
struct
i2c_client
*
client
;
struct
input_dev
*
input
;
struct
input_dev
*
input
;
char
phys
[
32
];
/* device physical location */
char
phys
[
32
];
/* device physical location */
int
irq
;
bool
irq_wake
;
/* irq wake is enabled */
bool
irq_wake
;
/* irq wake is enabled */
bool
smbus
;
bool
smbus
;
...
@@ -422,8 +421,8 @@ static ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values)
...
@@ -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
)
static
int
cyapa_get_state
(
struct
cyapa
*
cyapa
)
{
{
int
ret
;
u8
status
[
BL_STATUS_SIZE
];
u8
status
[
BL_STATUS_SIZE
];
int
error
;
cyapa
->
state
=
CYAPA_STATE_NO_DEVICE
;
cyapa
->
state
=
CYAPA_STATE_NO_DEVICE
;
...
@@ -433,18 +432,18 @@ static int cyapa_get_state(struct cyapa *cyapa)
...
@@ -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.
* 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
,
error
=
cyapa_i2c_reg_read_block
(
cyapa
,
BL_HEAD_OFFSET
,
BL_STATUS_SIZE
,
status
);
status
);
/*
/*
* On smbus systems in OP mode, the i2c_reg_read will fail with
* On smbus systems in OP mode, the i2c_reg_read will fail with
* -ETIMEDOUT. In this case, try again using the smbus equivalent
* -ETIMEDOUT. In this case, try again using the smbus equivalent
* command. This should return a BL_HEAD indicating CYAPA_STATE_OP.
* command. This should return a BL_HEAD indicating CYAPA_STATE_OP.
*/
*/
if
(
cyapa
->
smbus
&&
(
ret
==
-
ETIMEDOUT
||
ret
==
-
ENXIO
))
if
(
cyapa
->
smbus
&&
(
error
==
-
ETIMEDOUT
||
error
==
-
ENXIO
))
ret
=
cyapa_read_block
(
cyapa
,
CYAPA_CMD_BL_STATUS
,
status
);
error
=
cyapa_read_block
(
cyapa
,
CYAPA_CMD_BL_STATUS
,
status
);
if
(
ret
!=
BL_STATUS_SIZE
)
if
(
error
!=
BL_STATUS_SIZE
)
goto
error
;
goto
error
;
if
((
status
[
REG_OP_STATUS
]
&
OP_STATUS_SRC
)
==
OP_STATUS_SRC
)
{
if
((
status
[
REG_OP_STATUS
]
&
OP_STATUS_SRC
)
==
OP_STATUS_SRC
)
{
...
@@ -454,7 +453,7 @@ static int cyapa_get_state(struct cyapa *cyapa)
...
@@ -454,7 +453,7 @@ static int cyapa_get_state(struct cyapa *cyapa)
cyapa
->
state
=
CYAPA_STATE_OP
;
cyapa
->
state
=
CYAPA_STATE_OP
;
break
;
break
;
default:
default:
ret
=
-
EAGAIN
;
error
=
-
EAGAIN
;
goto
error
;
goto
error
;
}
}
}
else
{
}
else
{
...
@@ -468,7 +467,7 @@ static int cyapa_get_state(struct cyapa *cyapa)
...
@@ -468,7 +467,7 @@ static int cyapa_get_state(struct cyapa *cyapa)
return
0
;
return
0
;
error:
error:
return
(
ret
<
0
)
?
ret
:
-
EAGAIN
;
return
(
error
<
0
)
?
error
:
-
EAGAIN
;
}
}
/*
/*
...
@@ -487,31 +486,31 @@ static int cyapa_get_state(struct cyapa *cyapa)
...
@@ -487,31 +486,31 @@ static int cyapa_get_state(struct cyapa *cyapa)
*/
*/
static
int
cyapa_poll_state
(
struct
cyapa
*
cyapa
,
unsigned
int
timeout
)
static
int
cyapa_poll_state
(
struct
cyapa
*
cyapa
,
unsigned
int
timeout
)
{
{
int
ret
;
int
error
;
int
tries
=
timeout
/
100
;
int
tries
=
timeout
/
100
;
ret
=
cyapa_get_state
(
cyapa
);
error
=
cyapa_get_state
(
cyapa
);
while
((
ret
||
cyapa
->
state
>=
CYAPA_STATE_BL_BUSY
)
&&
tries
--
)
{
while
((
error
||
cyapa
->
state
>=
CYAPA_STATE_BL_BUSY
)
&&
tries
--
)
{
msleep
(
100
);
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
)
static
int
cyapa_bl_deactivate
(
struct
cyapa
*
cyapa
)
{
{
int
ret
;
int
error
;
ret
=
cyapa_i2c_reg_write_block
(
cyapa
,
0
,
sizeof
(
bl_deactivate
),
error
=
cyapa_i2c_reg_write_block
(
cyapa
,
0
,
sizeof
(
bl_deactivate
),
bl_deactivate
);
bl_deactivate
);
if
(
ret
<
0
)
if
(
error
)
return
ret
;
return
error
;
/* wait for bootloader to switch to idle state; should take < 100ms */
/* wait for bootloader to switch to idle state; should take < 100ms */
msleep
(
100
);
msleep
(
100
);
ret
=
cyapa_poll_state
(
cyapa
,
500
);
error
=
cyapa_poll_state
(
cyapa
,
500
);
if
(
ret
<
0
)
if
(
error
)
return
ret
;
return
error
;
if
(
cyapa
->
state
!=
CYAPA_STATE_BL_IDLE
)
if
(
cyapa
->
state
!=
CYAPA_STATE_BL_IDLE
)
return
-
EAGAIN
;
return
-
EAGAIN
;
return
0
;
return
0
;
...
@@ -532,11 +531,11 @@ static int cyapa_bl_deactivate(struct cyapa *cyapa)
...
@@ -532,11 +531,11 @@ static int cyapa_bl_deactivate(struct cyapa *cyapa)
*/
*/
static
int
cyapa_bl_exit
(
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
);
error
=
cyapa_i2c_reg_write_block
(
cyapa
,
0
,
sizeof
(
bl_exit
),
bl_exit
);
if
(
ret
<
0
)
if
(
error
)
return
ret
;
return
error
;
/*
/*
* Wait for bootloader to exit, and operation mode to start.
* Wait for bootloader to exit, and operation mode to start.
...
@@ -548,9 +547,9 @@ static int cyapa_bl_exit(struct cyapa *cyapa)
...
@@ -548,9 +547,9 @@ static int cyapa_bl_exit(struct cyapa *cyapa)
* updated to new firmware, it must first calibrate its sensors, which
* updated to new firmware, it must first calibrate its sensors, which
* can take up to an additional 2 seconds.
* can take up to an additional 2 seconds.
*/
*/
ret
=
cyapa_poll_state
(
cyapa
,
2000
);
error
=
cyapa_poll_state
(
cyapa
,
2000
);
if
(
ret
<
0
)
if
(
error
<
0
)
return
ret
;
return
error
;
if
(
cyapa
->
state
!=
CYAPA_STATE_OP
)
if
(
cyapa
->
state
!=
CYAPA_STATE_OP
)
return
-
EAGAIN
;
return
-
EAGAIN
;
...
@@ -577,10 +576,13 @@ static int cyapa_set_power_mode(struct cyapa *cyapa, u8 power_mode)
...
@@ -577,10 +576,13 @@ static int cyapa_set_power_mode(struct cyapa *cyapa, u8 power_mode)
power
=
ret
&
~
PWR_MODE_MASK
;
power
=
ret
&
~
PWR_MODE_MASK
;
power
|=
power_mode
&
PWR_MODE_MASK
;
power
|=
power_mode
&
PWR_MODE_MASK
;
ret
=
cyapa_write_byte
(
cyapa
,
CYAPA_CMD_POWER_MODE
,
power
);
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
"
,
dev_err
(
dev
,
"failed to set power_mode 0x%02x err = %d
\n
"
,
power_mode
,
ret
);
power_mode
,
ret
);
return
ret
;
return
ret
;
}
return
0
;
}
}
static
int
cyapa_get_query_data
(
struct
cyapa
*
cyapa
)
static
int
cyapa_get_query_data
(
struct
cyapa
*
cyapa
)
...
@@ -637,28 +639,28 @@ static int cyapa_check_is_operational(struct cyapa *cyapa)
...
@@ -637,28 +639,28 @@ static int cyapa_check_is_operational(struct cyapa *cyapa)
{
{
struct
device
*
dev
=
&
cyapa
->
client
->
dev
;
struct
device
*
dev
=
&
cyapa
->
client
->
dev
;
static
const
char
unique_str
[]
=
"CYTRA"
;
static
const
char
unique_str
[]
=
"CYTRA"
;
int
ret
;
int
error
;
ret
=
cyapa_poll_state
(
cyapa
,
2000
);
error
=
cyapa_poll_state
(
cyapa
,
2000
);
if
(
ret
<
0
)
if
(
error
)
return
ret
;
return
error
;
switch
(
cyapa
->
state
)
{
switch
(
cyapa
->
state
)
{
case
CYAPA_STATE_BL_ACTIVE
:
case
CYAPA_STATE_BL_ACTIVE
:
ret
=
cyapa_bl_deactivate
(
cyapa
);
error
=
cyapa_bl_deactivate
(
cyapa
);
if
(
ret
)
if
(
error
)
return
ret
;
return
error
;
/* Fallthrough state */
/* Fallthrough state */
case
CYAPA_STATE_BL_IDLE
:
case
CYAPA_STATE_BL_IDLE
:
ret
=
cyapa_bl_exit
(
cyapa
);
error
=
cyapa_bl_exit
(
cyapa
);
if
(
ret
)
if
(
error
)
return
ret
;
return
error
;
/* Fallthrough state */
/* Fallthrough state */
case
CYAPA_STATE_OP
:
case
CYAPA_STATE_OP
:
ret
=
cyapa_get_query_data
(
cyapa
);
error
=
cyapa_get_query_data
(
cyapa
);
if
(
ret
<
0
)
if
(
error
)
return
ret
;
return
error
;
/* only support firmware protocol gen3 */
/* only support firmware protocol gen3 */
if
(
cyapa
->
gen
!=
CYAPA_GEN3
)
{
if
(
cyapa
->
gen
!=
CYAPA_GEN3
)
{
...
@@ -753,18 +755,42 @@ static u8 cyapa_check_adapter_functionality(struct i2c_client *client)
...
@@ -753,18 +755,42 @@ static u8 cyapa_check_adapter_functionality(struct i2c_client *client)
return
ret
;
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
)
static
int
cyapa_create_input_dev
(
struct
cyapa
*
cyapa
)
{
{
struct
device
*
dev
=
&
cyapa
->
client
->
dev
;
struct
device
*
dev
=
&
cyapa
->
client
->
dev
;
int
ret
;
struct
input_dev
*
input
;
struct
input_dev
*
input
;
int
error
;
if
(
!
cyapa
->
physical_size_x
||
!
cyapa
->
physical_size_y
)
if
(
!
cyapa
->
physical_size_x
||
!
cyapa
->
physical_size_y
)
return
-
EINVAL
;
return
-
EINVAL
;
input
=
cyapa
->
input
=
input_allocate_device
(
);
input
=
devm_input_allocate_device
(
dev
);
if
(
!
input
)
{
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
;
return
-
ENOMEM
;
}
}
...
@@ -772,14 +798,17 @@ static int cyapa_create_input_dev(struct cyapa *cyapa)
...
@@ -772,14 +798,17 @@ static int cyapa_create_input_dev(struct cyapa *cyapa)
input
->
phys
=
cyapa
->
phys
;
input
->
phys
=
cyapa
->
phys
;
input
->
id
.
bustype
=
BUS_I2C
;
input
->
id
.
bustype
=
BUS_I2C
;
input
->
id
.
version
=
1
;
input
->
id
.
version
=
1
;
input
->
id
.
product
=
0
;
/*
m
eans any product in eventcomm. */
input
->
id
.
product
=
0
;
/*
M
eans any product in eventcomm. */
input
->
dev
.
parent
=
&
cyapa
->
client
->
dev
;
input
->
dev
.
parent
=
&
cyapa
->
client
->
dev
;
input
->
open
=
cyapa_open
;
input
->
close
=
cyapa_close
;
input_set_drvdata
(
input
,
cyapa
);
input_set_drvdata
(
input
,
cyapa
);
__set_bit
(
EV_ABS
,
input
->
evbit
);
__set_bit
(
EV_ABS
,
input
->
evbit
);
/*
f
inger position */
/*
F
inger position */
input_set_abs_params
(
input
,
ABS_MT_POSITION_X
,
0
,
cyapa
->
max_abs_x
,
0
,
input_set_abs_params
(
input
,
ABS_MT_POSITION_X
,
0
,
cyapa
->
max_abs_x
,
0
,
0
);
0
);
input_set_abs_params
(
input
,
ABS_MT_POSITION_Y
,
0
,
cyapa
->
max_abs_y
,
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)
...
@@ -801,35 +830,25 @@ static int cyapa_create_input_dev(struct cyapa *cyapa)
if
(
cyapa
->
btn_capability
==
CAPABILITY_LEFT_BTN_MASK
)
if
(
cyapa
->
btn_capability
==
CAPABILITY_LEFT_BTN_MASK
)
__set_bit
(
INPUT_PROP_BUTTONPAD
,
input
->
propbit
);
__set_bit
(
INPUT_PROP_BUTTONPAD
,
input
->
propbit
);
/*
h
andle pointer emulation and unused slots in core */
/*
H
andle pointer emulation and unused slots in core */
ret
=
input_mt_init_slots
(
input
,
CYAPA_MAX_MT_SLOTS
,
error
=
input_mt_init_slots
(
input
,
CYAPA_MAX_MT_SLOTS
,
INPUT_MT_POINTER
|
INPUT_MT_DROP_UNUSED
);
INPUT_MT_POINTER
|
INPUT_MT_DROP_UNUSED
);
if
(
ret
)
{
if
(
error
)
{
dev_err
(
dev
,
"
allocate memory for MT slots failed, %d
\n
"
,
ret
);
dev_err
(
dev
,
"
failed to initialize MT slots: %d
\n
"
,
error
);
goto
err_free_device
;
return
error
;
}
}
/* Register the device in input subsystem */
cyapa
->
input
=
input
;
ret
=
input_register_device
(
input
);
if
(
ret
)
{
dev_err
(
dev
,
"input device register failed, %d
\n
"
,
ret
);
goto
err_free_device
;
}
return
0
;
return
0
;
err_free_device:
input_free_device
(
input
);
cyapa
->
input
=
NULL
;
return
ret
;
}
}
static
int
cyapa_probe
(
struct
i2c_client
*
client
,
static
int
cyapa_probe
(
struct
i2c_client
*
client
,
const
struct
i2c_device_id
*
dev_id
)
const
struct
i2c_device_id
*
dev_id
)
{
{
int
ret
;
u8
adapter_func
;
struct
cyapa
*
cyapa
;
struct
device
*
dev
=
&
client
->
dev
;
struct
device
*
dev
=
&
client
->
dev
;
struct
cyapa
*
cyapa
;
u8
adapter_func
;
int
error
;
adapter_func
=
cyapa_check_adapter_functionality
(
client
);
adapter_func
=
cyapa_check_adapter_functionality
(
client
);
if
(
adapter_func
==
CYAPA_ADAPTER_FUNC_NONE
)
{
if
(
adapter_func
==
CYAPA_ADAPTER_FUNC_NONE
)
{
...
@@ -837,11 +856,9 @@ static int cyapa_probe(struct i2c_client *client,
...
@@ -837,11 +856,9 @@ static int cyapa_probe(struct i2c_client *client,
return
-
EIO
;
return
-
EIO
;
}
}
cyapa
=
kzalloc
(
sizeof
(
struct
cyapa
),
GFP_KERNEL
);
cyapa
=
devm_kzalloc
(
dev
,
sizeof
(
struct
cyapa
),
GFP_KERNEL
);
if
(
!
cyapa
)
{
if
(
!
cyapa
)
dev_err
(
dev
,
"allocate memory for cyapa failed
\n
"
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
cyapa
->
gen
=
CYAPA_GEN3
;
cyapa
->
gen
=
CYAPA_GEN3
;
cyapa
->
client
=
client
;
cyapa
->
client
=
client
;
...
@@ -852,67 +869,61 @@ static int cyapa_probe(struct i2c_client *client,
...
@@ -852,67 +869,61 @@ static int cyapa_probe(struct i2c_client *client,
/* i2c isn't supported, use smbus */
/* i2c isn't supported, use smbus */
if
(
adapter_func
==
CYAPA_ADAPTER_FUNC_SMBUS
)
if
(
adapter_func
==
CYAPA_ADAPTER_FUNC_SMBUS
)
cyapa
->
smbus
=
true
;
cyapa
->
smbus
=
true
;
cyapa
->
state
=
CYAPA_STATE_NO_DEVICE
;
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
;
}
ret
=
cyapa_create_input_dev
(
cyapa
);
error
=
cyapa_check_is_operational
(
cyapa
);
if
(
ret
)
{
if
(
error
)
{
dev_err
(
dev
,
"
create input_dev instance failed, %d
\n
"
,
ret
);
dev_err
(
dev
,
"
device not operational, %d
\n
"
,
error
);
goto
err_mem_free
;
return
error
;
}
}
ret
=
cyapa_set_power_mode
(
cyapa
,
PWR_MODE_FULL_ACTIVE
);
/* Power down the device until we need it */
if
(
ret
)
{
error
=
cyapa_set_power_mode
(
cyapa
,
PWR_MODE_OFF
);
dev_err
(
dev
,
"set active power failed, %d
\n
"
,
ret
);
if
(
error
)
{
goto
err_unregister_device
;
dev_err
(
dev
,
"failed to quiesce the device: %d
\n
"
,
error
);
return
error
;
}
}
cyapa
->
irq
=
client
->
irq
;
error
=
cyapa_create_input_dev
(
cyapa
);
ret
=
request_threaded_irq
(
cyapa
->
irq
,
if
(
error
)
NULL
,
return
error
;
cyapa_irq
,
IRQF_TRIGGER_FALLING
|
IRQF_ONESHOT
,
error
=
devm_request_threaded_irq
(
dev
,
client
->
irq
,
"cyapa"
,
NULL
,
cyapa_irq
,
cyapa
);
IRQF_TRIGGER_FALLING
|
IRQF_ONESHOT
,
if
(
ret
)
{
"cyapa"
,
cyapa
);
dev_err
(
dev
,
"IRQ request failed: %d
\n
, "
,
ret
);
if
(
error
)
{
goto
err_unregister_device
;
dev_err
(
dev
,
"failed to request threaded irq: %d
\n
"
,
error
);
return
error
;
}
}
return
0
;
/* Disable IRQ until the device is opened */
disable_irq
(
client
->
irq
);
err_unregister_device:
/* Register the device in input subsystem */
input_unregister_device
(
cyapa
->
input
);
error
=
input_register_device
(
cyapa
->
input
);
err_mem_free:
if
(
error
)
{
kfree
(
cyapa
);
dev_err
(
dev
,
"failed to register input device: %d
\n
"
,
error
);
return
error
;
return
ret
;
}
}
static
int
cyapa_remove
(
struct
i2c_client
*
client
)
{
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
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
cyapa_suspend
(
struct
device
*
dev
)
static
int
cyapa_suspend
(
struct
device
*
dev
)
{
{
int
ret
;
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
cyapa
*
cyapa
=
i2c_get_clientdata
(
client
);
struct
input_dev
*
input
=
cyapa
->
input
;
u8
power_mode
;
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,
* Set trackpad device to idle mode if wakeup is allowed,
...
@@ -920,31 +931,44 @@ static int cyapa_suspend(struct device *dev)
...
@@ -920,31 +931,44 @@ static int cyapa_suspend(struct device *dev)
*/
*/
power_mode
=
device_may_wakeup
(
dev
)
?
PWR_MODE_IDLE
power_mode
=
device_may_wakeup
(
dev
)
?
PWR_MODE_IDLE
:
PWR_MODE_OFF
;
:
PWR_MODE_OFF
;
ret
=
cyapa_set_power_mode
(
cyapa
,
power_mode
);
error
=
cyapa_set_power_mode
(
cyapa
,
power_mode
);
if
(
ret
<
0
)
if
(
error
)
dev_err
(
dev
,
"set power mode failed, %d
\n
"
,
ret
);
dev_err
(
dev
,
"resume: set power mode to %d failed: %d
\n
"
,
power_mode
,
error
);
if
(
device_may_wakeup
(
dev
))
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
;
return
0
;
}
}
static
int
cyapa_resume
(
struct
device
*
dev
)
static
int
__maybe_unused
cyapa_resume
(
struct
device
*
dev
)
{
{
int
ret
;
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
cyapa
*
cyapa
=
dev_get_drvdata
(
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
)
if
(
device_may_wakeup
(
dev
)
&&
cyapa
->
irq_wake
)
disable_irq_wake
(
cyapa
->
irq
);
disable_irq_wake
(
client
->
irq
);
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
);
ret
=
cyapa_set_power_mode
(
cyapa
,
PWR_MODE_FULL_ACTIVE
);
mutex_unlock
(
&
input
->
mutex
);
if
(
ret
)
dev_warn
(
dev
,
"resume active power failed, %d
\n
"
,
ret
);
enable_irq
(
cyapa
->
irq
);
return
0
;
return
0
;
}
}
#endif
/* CONFIG_PM_SLEEP */
static
SIMPLE_DEV_PM_OPS
(
cyapa_pm_ops
,
cyapa_suspend
,
cyapa_resume
);
static
SIMPLE_DEV_PM_OPS
(
cyapa_pm_ops
,
cyapa_suspend
,
cyapa_resume
);
...
@@ -962,7 +986,6 @@ static struct i2c_driver cyapa_driver = {
...
@@ -962,7 +986,6 @@ static struct i2c_driver cyapa_driver = {
},
},
.
probe
=
cyapa_probe
,
.
probe
=
cyapa_probe
,
.
remove
=
cyapa_remove
,
.
id_table
=
cyapa_id_table
,
.
id_table
=
cyapa_id_table
,
};
};
...
...
drivers/input/mouse/elan_i2c.h
0 → 100644
浏览文件 @
f20c86cd
/*
* 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 */
drivers/input/mouse/elan_i2c_core.c
0 → 100644
浏览文件 @
f20c86cd
/*
* 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.
*/
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/input.h>
#include <linux/uaccess.h>
#include <linux/jiffies.h>
#include <linux/completion.h>
#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <asm/unaligned.h>
#include "elan_i2c.h"
#define DRIVER_NAME "elan_i2c"
#define ELAN_DRIVER_VERSION "1.5.5"
#define ETP_PRESSURE_OFFSET 25
#define ETP_MAX_PRESSURE 255
#define ETP_FWIDTH_REDUCE 90
#define ETP_FINGER_WIDTH 15
#define ETP_RETRY_COUNT 3
#define ETP_MAX_FINGERS 5
#define ETP_FINGER_DATA_LEN 5
#define ETP_REPORT_ID 0x5D
#define ETP_REPORT_ID_OFFSET 2
#define ETP_TOUCH_INFO_OFFSET 3
#define ETP_FINGER_DATA_OFFSET 4
#define ETP_MAX_REPORT_LEN 34
/* The main device structure */
struct
elan_tp_data
{
struct
i2c_client
*
client
;
struct
input_dev
*
input
;
struct
regulator
*
vcc
;
const
struct
elan_transport_ops
*
ops
;
/* for fw update */
struct
completion
fw_completion
;
bool
in_fw_update
;
struct
mutex
sysfs_mutex
;
unsigned
int
max_x
;
unsigned
int
max_y
;
unsigned
int
width_x
;
unsigned
int
width_y
;
unsigned
int
x_res
;
unsigned
int
y_res
;
u8
product_id
;
u8
fw_version
;
u8
sm_version
;
u8
iap_version
;
u16
fw_checksum
;
u8
mode
;
bool
irq_wake
;
u8
min_baseline
;
u8
max_baseline
;
bool
baseline_ready
;
};
static
int
elan_enable_power
(
struct
elan_tp_data
*
data
)
{
int
repeat
=
ETP_RETRY_COUNT
;
int
error
;
error
=
regulator_enable
(
data
->
vcc
);
if
(
error
)
{
dev_err
(
&
data
->
client
->
dev
,
"Failed to enable regulator: %d
\n
"
,
error
);
return
error
;
}
do
{
error
=
data
->
ops
->
power_control
(
data
->
client
,
true
);
if
(
error
>=
0
)
return
0
;
msleep
(
30
);
}
while
(
--
repeat
>
0
);
return
error
;
}
static
int
elan_disable_power
(
struct
elan_tp_data
*
data
)
{
int
repeat
=
ETP_RETRY_COUNT
;
int
error
;
do
{
error
=
data
->
ops
->
power_control
(
data
->
client
,
false
);
if
(
!
error
)
{
error
=
regulator_disable
(
data
->
vcc
);
if
(
error
)
{
dev_err
(
&
data
->
client
->
dev
,
"Failed to disable regulator: %d
\n
"
,
error
);
/* Attempt to power the chip back up */
data
->
ops
->
power_control
(
data
->
client
,
true
);
break
;
}
return
0
;
}
msleep
(
30
);
}
while
(
--
repeat
>
0
);
return
error
;
}
static
int
elan_sleep
(
struct
elan_tp_data
*
data
)
{
int
repeat
=
ETP_RETRY_COUNT
;
int
error
;
do
{
error
=
data
->
ops
->
sleep_control
(
data
->
client
,
true
);
if
(
!
error
)
return
0
;
msleep
(
30
);
}
while
(
--
repeat
>
0
);
return
error
;
}
static
int
__elan_initialize
(
struct
elan_tp_data
*
data
)
{
struct
i2c_client
*
client
=
data
->
client
;
int
error
;
error
=
data
->
ops
->
initialize
(
client
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"device initialize failed: %d
\n
"
,
error
);
return
error
;
}
data
->
mode
|=
ETP_ENABLE_ABS
;
error
=
data
->
ops
->
set_mode
(
client
,
data
->
mode
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"failed to switch to absolute mode: %d
\n
"
,
error
);
return
error
;
}
error
=
data
->
ops
->
sleep_control
(
client
,
false
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"failed to wake device up: %d
\n
"
,
error
);
return
error
;
}
return
0
;
}
static
int
elan_initialize
(
struct
elan_tp_data
*
data
)
{
int
repeat
=
ETP_RETRY_COUNT
;
int
error
;
do
{
error
=
__elan_initialize
(
data
);
if
(
!
error
)
return
0
;
repeat
--
;
msleep
(
30
);
}
while
(
--
repeat
>
0
);
return
error
;
}
static
int
elan_query_device_info
(
struct
elan_tp_data
*
data
)
{
int
error
;
error
=
data
->
ops
->
get_product_id
(
data
->
client
,
&
data
->
product_id
);
if
(
error
)
return
error
;
error
=
data
->
ops
->
get_version
(
data
->
client
,
false
,
&
data
->
fw_version
);
if
(
error
)
return
error
;
error
=
data
->
ops
->
get_checksum
(
data
->
client
,
false
,
&
data
->
fw_checksum
);
if
(
error
)
return
error
;
error
=
data
->
ops
->
get_sm_version
(
data
->
client
,
&
data
->
sm_version
);
if
(
error
)
return
error
;
error
=
data
->
ops
->
get_version
(
data
->
client
,
true
,
&
data
->
iap_version
);
if
(
error
)
return
error
;
return
0
;
}
static
unsigned
int
elan_convert_resolution
(
u8
val
)
{
/*
* (value from firmware) * 10 + 790 = dpi
*
* We also have to convert dpi to dots/mm (*10/254 to avoid floating
* point).
*/
return
((
int
)(
char
)
val
*
10
+
790
)
*
10
/
254
;
}
static
int
elan_query_device_parameters
(
struct
elan_tp_data
*
data
)
{
unsigned
int
x_traces
,
y_traces
;
u8
hw_x_res
,
hw_y_res
;
int
error
;
error
=
data
->
ops
->
get_max
(
data
->
client
,
&
data
->
max_x
,
&
data
->
max_y
);
if
(
error
)
return
error
;
error
=
data
->
ops
->
get_num_traces
(
data
->
client
,
&
x_traces
,
&
y_traces
);
if
(
error
)
return
error
;
data
->
width_x
=
data
->
max_x
/
x_traces
;
data
->
width_y
=
data
->
max_y
/
y_traces
;
error
=
data
->
ops
->
get_resolution
(
data
->
client
,
&
hw_x_res
,
&
hw_y_res
);
if
(
error
)
return
error
;
data
->
x_res
=
elan_convert_resolution
(
hw_x_res
);
data
->
y_res
=
elan_convert_resolution
(
hw_y_res
);
return
0
;
}
/*
**********************************************************
* IAP firmware updater related routines
**********************************************************
*/
static
int
elan_write_fw_block
(
struct
elan_tp_data
*
data
,
const
u8
*
page
,
u16
checksum
,
int
idx
)
{
int
retry
=
ETP_RETRY_COUNT
;
int
error
;
do
{
error
=
data
->
ops
->
write_fw_block
(
data
->
client
,
page
,
checksum
,
idx
);
if
(
!
error
)
return
0
;
dev_dbg
(
&
data
->
client
->
dev
,
"IAP retrying page %d (error: %d)
\n
"
,
idx
,
error
);
}
while
(
--
retry
>
0
);
return
error
;
}
static
int
__elan_update_firmware
(
struct
elan_tp_data
*
data
,
const
struct
firmware
*
fw
)
{
struct
i2c_client
*
client
=
data
->
client
;
struct
device
*
dev
=
&
client
->
dev
;
int
i
,
j
;
int
error
;
u16
iap_start_addr
;
u16
boot_page_count
;
u16
sw_checksum
=
0
,
fw_checksum
=
0
;
error
=
data
->
ops
->
prepare_fw_update
(
client
);
if
(
error
)
return
error
;
iap_start_addr
=
get_unaligned_le16
(
&
fw
->
data
[
ETP_IAP_START_ADDR
*
2
]);
boot_page_count
=
(
iap_start_addr
*
2
)
/
ETP_FW_PAGE_SIZE
;
for
(
i
=
boot_page_count
;
i
<
ETP_FW_PAGE_COUNT
;
i
++
)
{
u16
checksum
=
0
;
const
u8
*
page
=
&
fw
->
data
[
i
*
ETP_FW_PAGE_SIZE
];
for
(
j
=
0
;
j
<
ETP_FW_PAGE_SIZE
;
j
+=
2
)
checksum
+=
((
page
[
j
+
1
]
<<
8
)
|
page
[
j
]);
error
=
elan_write_fw_block
(
data
,
page
,
checksum
,
i
);
if
(
error
)
{
dev_err
(
dev
,
"write page %d fail: %d
\n
"
,
i
,
error
);
return
error
;
}
sw_checksum
+=
checksum
;
}
/* Wait WDT reset and power on reset */
msleep
(
600
);
error
=
data
->
ops
->
finish_fw_update
(
client
,
&
data
->
fw_completion
);
if
(
error
)
return
error
;
error
=
data
->
ops
->
get_checksum
(
client
,
true
,
&
fw_checksum
);
if
(
error
)
return
error
;
if
(
sw_checksum
!=
fw_checksum
)
{
dev_err
(
dev
,
"checksum diff sw=[%04X], fw=[%04X]
\n
"
,
sw_checksum
,
fw_checksum
);
return
-
EIO
;
}
return
0
;
}
static
int
elan_update_firmware
(
struct
elan_tp_data
*
data
,
const
struct
firmware
*
fw
)
{
struct
i2c_client
*
client
=
data
->
client
;
int
retval
;
dev_dbg
(
&
client
->
dev
,
"Starting firmware update....
\n
"
);
disable_irq
(
client
->
irq
);
data
->
in_fw_update
=
true
;
retval
=
__elan_update_firmware
(
data
,
fw
);
if
(
retval
)
{
dev_err
(
&
client
->
dev
,
"firmware update failed: %d
\n
"
,
retval
);
data
->
ops
->
iap_reset
(
client
);
}
else
{
/* Reinitialize TP after fw is updated */
elan_initialize
(
data
);
elan_query_device_info
(
data
);
}
data
->
in_fw_update
=
false
;
enable_irq
(
client
->
irq
);
return
retval
;
}
/*
*******************************************************************
* SYSFS attributes
*******************************************************************
*/
static
ssize_t
elan_sysfs_read_fw_checksum
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elan_tp_data
*
data
=
i2c_get_clientdata
(
client
);
return
sprintf
(
buf
,
"0x%04x
\n
"
,
data
->
fw_checksum
);
}
static
ssize_t
elan_sysfs_read_product_id
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elan_tp_data
*
data
=
i2c_get_clientdata
(
client
);
return
sprintf
(
buf
,
"%d.0
\n
"
,
data
->
product_id
);
}
static
ssize_t
elan_sysfs_read_fw_ver
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elan_tp_data
*
data
=
i2c_get_clientdata
(
client
);
return
sprintf
(
buf
,
"%d.0
\n
"
,
data
->
fw_version
);
}
static
ssize_t
elan_sysfs_read_sm_ver
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elan_tp_data
*
data
=
i2c_get_clientdata
(
client
);
return
sprintf
(
buf
,
"%d.0
\n
"
,
data
->
sm_version
);
}
static
ssize_t
elan_sysfs_read_iap_ver
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elan_tp_data
*
data
=
i2c_get_clientdata
(
client
);
return
sprintf
(
buf
,
"%d.0
\n
"
,
data
->
iap_version
);
}
static
ssize_t
elan_sysfs_update_fw
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elan_tp_data
*
data
=
i2c_get_clientdata
(
client
);
const
struct
firmware
*
fw
;
int
error
;
error
=
request_firmware
(
&
fw
,
ETP_FW_NAME
,
dev
);
if
(
error
)
{
dev_err
(
dev
,
"cannot load firmware %s: %d
\n
"
,
ETP_FW_NAME
,
error
);
return
error
;
}
/* Firmware must be exactly PAGE_NUM * PAGE_SIZE bytes */
if
(
fw
->
size
!=
ETP_FW_SIZE
)
{
dev_err
(
dev
,
"invalid firmware size = %zu, expected %d.
\n
"
,
fw
->
size
,
ETP_FW_SIZE
);
error
=
-
EBADF
;
goto
out_release_fw
;
}
error
=
mutex_lock_interruptible
(
&
data
->
sysfs_mutex
);
if
(
error
)
goto
out_release_fw
;
error
=
elan_update_firmware
(
data
,
fw
);
mutex_unlock
(
&
data
->
sysfs_mutex
);
out_release_fw:
release_firmware
(
fw
);
return
error
?:
count
;
}
static
ssize_t
calibrate_store
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elan_tp_data
*
data
=
i2c_get_clientdata
(
client
);
int
tries
=
20
;
int
retval
;
int
error
;
u8
val
[
3
];
retval
=
mutex_lock_interruptible
(
&
data
->
sysfs_mutex
);
if
(
retval
)
return
retval
;
disable_irq
(
client
->
irq
);
data
->
mode
|=
ETP_ENABLE_CALIBRATE
;
retval
=
data
->
ops
->
set_mode
(
client
,
data
->
mode
);
if
(
retval
)
{
dev_err
(
dev
,
"failed to enable calibration mode: %d
\n
"
,
retval
);
goto
out
;
}
retval
=
data
->
ops
->
calibrate
(
client
);
if
(
retval
)
{
dev_err
(
dev
,
"failed to start calibration: %d
\n
"
,
retval
);
goto
out_disable_calibrate
;
}
val
[
0
]
=
0xff
;
do
{
/* Wait 250ms before checking if calibration has completed. */
msleep
(
250
);
retval
=
data
->
ops
->
calibrate_result
(
client
,
val
);
if
(
retval
)
dev_err
(
dev
,
"failed to check calibration result: %d
\n
"
,
retval
);
else
if
(
val
[
0
]
==
0
)
break
;
/* calibration done */
}
while
(
--
tries
);
if
(
tries
==
0
)
{
dev_err
(
dev
,
"failed to calibrate. Timeout.
\n
"
);
retval
=
-
ETIMEDOUT
;
}
out_disable_calibrate:
data
->
mode
&=
~
ETP_ENABLE_CALIBRATE
;
error
=
data
->
ops
->
set_mode
(
data
->
client
,
data
->
mode
);
if
(
error
)
{
dev_err
(
dev
,
"failed to disable calibration mode: %d
\n
"
,
error
);
if
(
!
retval
)
retval
=
error
;
}
out:
enable_irq
(
client
->
irq
);
mutex_unlock
(
&
data
->
sysfs_mutex
);
return
retval
?:
count
;
}
static
ssize_t
elan_sysfs_read_mode
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elan_tp_data
*
data
=
i2c_get_clientdata
(
client
);
int
error
;
enum
tp_mode
mode
;
error
=
mutex_lock_interruptible
(
&
data
->
sysfs_mutex
);
if
(
error
)
return
error
;
error
=
data
->
ops
->
iap_get_mode
(
data
->
client
,
&
mode
);
mutex_unlock
(
&
data
->
sysfs_mutex
);
if
(
error
)
return
error
;
return
sprintf
(
buf
,
"%d
\n
"
,
(
int
)
mode
);
}
static
DEVICE_ATTR
(
product_id
,
S_IRUGO
,
elan_sysfs_read_product_id
,
NULL
);
static
DEVICE_ATTR
(
firmware_version
,
S_IRUGO
,
elan_sysfs_read_fw_ver
,
NULL
);
static
DEVICE_ATTR
(
sample_version
,
S_IRUGO
,
elan_sysfs_read_sm_ver
,
NULL
);
static
DEVICE_ATTR
(
iap_version
,
S_IRUGO
,
elan_sysfs_read_iap_ver
,
NULL
);
static
DEVICE_ATTR
(
fw_checksum
,
S_IRUGO
,
elan_sysfs_read_fw_checksum
,
NULL
);
static
DEVICE_ATTR
(
mode
,
S_IRUGO
,
elan_sysfs_read_mode
,
NULL
);
static
DEVICE_ATTR
(
update_fw
,
S_IWUSR
,
NULL
,
elan_sysfs_update_fw
);
static
DEVICE_ATTR_WO
(
calibrate
);
static
struct
attribute
*
elan_sysfs_entries
[]
=
{
&
dev_attr_product_id
.
attr
,
&
dev_attr_firmware_version
.
attr
,
&
dev_attr_sample_version
.
attr
,
&
dev_attr_iap_version
.
attr
,
&
dev_attr_fw_checksum
.
attr
,
&
dev_attr_calibrate
.
attr
,
&
dev_attr_mode
.
attr
,
&
dev_attr_update_fw
.
attr
,
NULL
,
};
static
const
struct
attribute_group
elan_sysfs_group
=
{
.
attrs
=
elan_sysfs_entries
,
};
static
ssize_t
acquire_store
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elan_tp_data
*
data
=
i2c_get_clientdata
(
client
);
int
error
;
int
retval
;
retval
=
mutex_lock_interruptible
(
&
data
->
sysfs_mutex
);
if
(
retval
)
return
retval
;
disable_irq
(
client
->
irq
);
data
->
baseline_ready
=
false
;
data
->
mode
|=
ETP_ENABLE_CALIBRATE
;
retval
=
data
->
ops
->
set_mode
(
data
->
client
,
data
->
mode
);
if
(
retval
)
{
dev_err
(
dev
,
"Failed to enable calibration mode to get baseline: %d
\n
"
,
retval
);
goto
out
;
}
msleep
(
250
);
retval
=
data
->
ops
->
get_baseline_data
(
data
->
client
,
true
,
&
data
->
max_baseline
);
if
(
retval
)
{
dev_err
(
dev
,
"Failed to read max baseline form device: %d
\n
"
,
retval
);
goto
out_disable_calibrate
;
}
retval
=
data
->
ops
->
get_baseline_data
(
data
->
client
,
false
,
&
data
->
min_baseline
);
if
(
retval
)
{
dev_err
(
dev
,
"Failed to read min baseline form device: %d
\n
"
,
retval
);
goto
out_disable_calibrate
;
}
data
->
baseline_ready
=
true
;
out_disable_calibrate:
data
->
mode
&=
~
ETP_ENABLE_CALIBRATE
;
error
=
data
->
ops
->
set_mode
(
data
->
client
,
data
->
mode
);
if
(
error
)
{
dev_err
(
dev
,
"Failed to disable calibration mode after acquiring baseline: %d
\n
"
,
error
);
if
(
!
retval
)
retval
=
error
;
}
out:
enable_irq
(
client
->
irq
);
mutex_unlock
(
&
data
->
sysfs_mutex
);
return
retval
?:
count
;
}
static
ssize_t
min_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elan_tp_data
*
data
=
i2c_get_clientdata
(
client
);
int
retval
;
retval
=
mutex_lock_interruptible
(
&
data
->
sysfs_mutex
);
if
(
retval
)
return
retval
;
if
(
!
data
->
baseline_ready
)
{
retval
=
-
ENODATA
;
goto
out
;
}
retval
=
snprintf
(
buf
,
PAGE_SIZE
,
"%d"
,
data
->
min_baseline
);
out:
mutex_unlock
(
&
data
->
sysfs_mutex
);
return
retval
;
}
static
ssize_t
max_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elan_tp_data
*
data
=
i2c_get_clientdata
(
client
);
int
retval
;
retval
=
mutex_lock_interruptible
(
&
data
->
sysfs_mutex
);
if
(
retval
)
return
retval
;
if
(
!
data
->
baseline_ready
)
{
retval
=
-
ENODATA
;
goto
out
;
}
retval
=
snprintf
(
buf
,
PAGE_SIZE
,
"%d"
,
data
->
max_baseline
);
out:
mutex_unlock
(
&
data
->
sysfs_mutex
);
return
retval
;
}
static
DEVICE_ATTR_WO
(
acquire
);
static
DEVICE_ATTR_RO
(
min
);
static
DEVICE_ATTR_RO
(
max
);
static
struct
attribute
*
elan_baseline_sysfs_entries
[]
=
{
&
dev_attr_acquire
.
attr
,
&
dev_attr_min
.
attr
,
&
dev_attr_max
.
attr
,
NULL
,
};
static
const
struct
attribute_group
elan_baseline_sysfs_group
=
{
.
name
=
"baseline"
,
.
attrs
=
elan_baseline_sysfs_entries
,
};
static
const
struct
attribute_group
*
elan_sysfs_groups
[]
=
{
&
elan_sysfs_group
,
&
elan_baseline_sysfs_group
,
NULL
};
/*
******************************************************************
* Elan isr functions
******************************************************************
*/
static
void
elan_report_contact
(
struct
elan_tp_data
*
data
,
int
contact_num
,
bool
contact_valid
,
u8
*
finger_data
)
{
struct
input_dev
*
input
=
data
->
input
;
unsigned
int
pos_x
,
pos_y
;
unsigned
int
pressure
,
mk_x
,
mk_y
;
unsigned
int
area_x
,
area_y
,
major
,
minor
,
new_pressure
;
if
(
contact_valid
)
{
pos_x
=
((
finger_data
[
0
]
&
0xf0
)
<<
4
)
|
finger_data
[
1
];
pos_y
=
((
finger_data
[
0
]
&
0x0f
)
<<
8
)
|
finger_data
[
2
];
mk_x
=
(
finger_data
[
3
]
&
0x0f
);
mk_y
=
(
finger_data
[
3
]
>>
4
);
pressure
=
finger_data
[
4
];
if
(
pos_x
>
data
->
max_x
||
pos_y
>
data
->
max_y
)
{
dev_dbg
(
input
->
dev
.
parent
,
"[%d] x=%d y=%d over max (%d, %d)"
,
contact_num
,
pos_x
,
pos_y
,
data
->
max_x
,
data
->
max_y
);
return
;
}
/*
* To avoid treating large finger as palm, let's reduce the
* width x and y per trace.
*/
area_x
=
mk_x
*
(
data
->
width_x
-
ETP_FWIDTH_REDUCE
);
area_y
=
mk_y
*
(
data
->
width_y
-
ETP_FWIDTH_REDUCE
);
major
=
max
(
area_x
,
area_y
);
minor
=
min
(
area_x
,
area_y
);
new_pressure
=
pressure
+
ETP_PRESSURE_OFFSET
;
if
(
new_pressure
>
ETP_MAX_PRESSURE
)
new_pressure
=
ETP_MAX_PRESSURE
;
input_mt_slot
(
input
,
contact_num
);
input_mt_report_slot_state
(
input
,
MT_TOOL_FINGER
,
true
);
input_report_abs
(
input
,
ABS_MT_POSITION_X
,
pos_x
);
input_report_abs
(
input
,
ABS_MT_POSITION_Y
,
data
->
max_y
-
pos_y
);
input_report_abs
(
input
,
ABS_MT_PRESSURE
,
new_pressure
);
input_report_abs
(
input
,
ABS_TOOL_WIDTH
,
mk_x
);
input_report_abs
(
input
,
ABS_MT_TOUCH_MAJOR
,
major
);
input_report_abs
(
input
,
ABS_MT_TOUCH_MINOR
,
minor
);
}
else
{
input_mt_slot
(
input
,
contact_num
);
input_mt_report_slot_state
(
input
,
MT_TOOL_FINGER
,
false
);
}
}
static
void
elan_report_absolute
(
struct
elan_tp_data
*
data
,
u8
*
packet
)
{
struct
input_dev
*
input
=
data
->
input
;
u8
*
finger_data
=
&
packet
[
ETP_FINGER_DATA_OFFSET
];
int
i
;
u8
tp_info
=
packet
[
ETP_TOUCH_INFO_OFFSET
];
bool
contact_valid
;
for
(
i
=
0
;
i
<
ETP_MAX_FINGERS
;
i
++
)
{
contact_valid
=
tp_info
&
(
1U
<<
(
3
+
i
));
elan_report_contact
(
data
,
i
,
contact_valid
,
finger_data
);
if
(
contact_valid
)
finger_data
+=
ETP_FINGER_DATA_LEN
;
}
input_report_key
(
input
,
BTN_LEFT
,
tp_info
&
0x01
);
input_mt_report_pointer_emulation
(
input
,
true
);
input_sync
(
input
);
}
static
irqreturn_t
elan_isr
(
int
irq
,
void
*
dev_id
)
{
struct
elan_tp_data
*
data
=
dev_id
;
struct
device
*
dev
=
&
data
->
client
->
dev
;
int
error
;
u8
report
[
ETP_MAX_REPORT_LEN
];
/*
* When device is connected to i2c bus, when all IAP page writes
* complete, the driver will receive interrupt and must read
* 0000 to confirm that IAP is finished.
*/
if
(
data
->
in_fw_update
)
{
complete
(
&
data
->
fw_completion
);
goto
out
;
}
error
=
data
->
ops
->
get_report
(
data
->
client
,
report
);
if
(
error
)
goto
out
;
if
(
report
[
ETP_REPORT_ID_OFFSET
]
!=
ETP_REPORT_ID
)
dev_err
(
dev
,
"invalid report id data (%x)
\n
"
,
report
[
ETP_REPORT_ID_OFFSET
]);
else
elan_report_absolute
(
data
,
report
);
out:
return
IRQ_HANDLED
;
}
/*
******************************************************************
* Elan initialization functions
******************************************************************
*/
static
int
elan_setup_input_device
(
struct
elan_tp_data
*
data
)
{
struct
device
*
dev
=
&
data
->
client
->
dev
;
struct
input_dev
*
input
;
unsigned
int
max_width
=
max
(
data
->
width_x
,
data
->
width_y
);
unsigned
int
min_width
=
min
(
data
->
width_x
,
data
->
width_y
);
int
error
;
input
=
devm_input_allocate_device
(
dev
);
if
(
!
input
)
return
-
ENOMEM
;
input
->
name
=
"Elan Touchpad"
;
input
->
id
.
bustype
=
BUS_I2C
;
input_set_drvdata
(
input
,
data
);
error
=
input_mt_init_slots
(
input
,
ETP_MAX_FINGERS
,
INPUT_MT_POINTER
|
INPUT_MT_DROP_UNUSED
);
if
(
error
)
{
dev_err
(
dev
,
"failed to initialize MT slots: %d
\n
"
,
error
);
return
error
;
}
__set_bit
(
EV_ABS
,
input
->
evbit
);
__set_bit
(
INPUT_PROP_POINTER
,
input
->
propbit
);
__set_bit
(
INPUT_PROP_BUTTONPAD
,
input
->
propbit
);
__set_bit
(
BTN_LEFT
,
input
->
keybit
);
/* Set up ST parameters */
input_set_abs_params
(
input
,
ABS_X
,
0
,
data
->
max_x
,
0
,
0
);
input_set_abs_params
(
input
,
ABS_Y
,
0
,
data
->
max_y
,
0
,
0
);
input_abs_set_res
(
input
,
ABS_X
,
data
->
x_res
);
input_abs_set_res
(
input
,
ABS_Y
,
data
->
y_res
);
input_set_abs_params
(
input
,
ABS_PRESSURE
,
0
,
ETP_MAX_PRESSURE
,
0
,
0
);
input_set_abs_params
(
input
,
ABS_TOOL_WIDTH
,
0
,
ETP_FINGER_WIDTH
,
0
,
0
);
/* And MT parameters */
input_set_abs_params
(
input
,
ABS_MT_POSITION_X
,
0
,
data
->
max_x
,
0
,
0
);
input_set_abs_params
(
input
,
ABS_MT_POSITION_Y
,
0
,
data
->
max_y
,
0
,
0
);
input_abs_set_res
(
input
,
ABS_MT_POSITION_X
,
data
->
x_res
);
input_abs_set_res
(
input
,
ABS_MT_POSITION_Y
,
data
->
y_res
);
input_set_abs_params
(
input
,
ABS_MT_PRESSURE
,
0
,
ETP_MAX_PRESSURE
,
0
,
0
);
input_set_abs_params
(
input
,
ABS_MT_TOUCH_MAJOR
,
0
,
ETP_FINGER_WIDTH
*
max_width
,
0
,
0
);
input_set_abs_params
(
input
,
ABS_MT_TOUCH_MINOR
,
0
,
ETP_FINGER_WIDTH
*
min_width
,
0
,
0
);
data
->
input
=
input
;
return
0
;
}
static
void
elan_disable_regulator
(
void
*
_data
)
{
struct
elan_tp_data
*
data
=
_data
;
regulator_disable
(
data
->
vcc
);
}
static
void
elan_remove_sysfs_groups
(
void
*
_data
)
{
struct
elan_tp_data
*
data
=
_data
;
sysfs_remove_groups
(
&
data
->
client
->
dev
.
kobj
,
elan_sysfs_groups
);
}
static
int
elan_probe
(
struct
i2c_client
*
client
,
const
struct
i2c_device_id
*
dev_id
)
{
const
struct
elan_transport_ops
*
transport_ops
;
struct
device
*
dev
=
&
client
->
dev
;
struct
elan_tp_data
*
data
;
unsigned
long
irqflags
;
int
error
;
if
(
IS_ENABLED
(
CONFIG_MOUSE_ELAN_I2C_I2C
)
&&
i2c_check_functionality
(
client
->
adapter
,
I2C_FUNC_I2C
))
{
transport_ops
=
&
elan_i2c_ops
;
}
else
if
(
IS_ENABLED
(
CONFIG_MOUSE_ELAN_I2C_SMBUS
)
&&
i2c_check_functionality
(
client
->
adapter
,
I2C_FUNC_SMBUS_BYTE_DATA
|
I2C_FUNC_SMBUS_BLOCK_DATA
|
I2C_FUNC_SMBUS_I2C_BLOCK
))
{
transport_ops
=
&
elan_smbus_ops
;
}
else
{
dev_err
(
dev
,
"not a supported I2C/SMBus adapter
\n
"
);
return
-
EIO
;
}
data
=
devm_kzalloc
(
&
client
->
dev
,
sizeof
(
struct
elan_tp_data
),
GFP_KERNEL
);
if
(
!
data
)
return
-
ENOMEM
;
i2c_set_clientdata
(
client
,
data
);
data
->
ops
=
transport_ops
;
data
->
client
=
client
;
init_completion
(
&
data
->
fw_completion
);
mutex_init
(
&
data
->
sysfs_mutex
);
data
->
vcc
=
devm_regulator_get
(
&
client
->
dev
,
"vcc"
);
if
(
IS_ERR
(
data
->
vcc
))
{
error
=
PTR_ERR
(
data
->
vcc
);
if
(
error
!=
-
EPROBE_DEFER
)
dev_err
(
&
client
->
dev
,
"Failed to get 'vcc' regulator: %d
\n
"
,
error
);
return
error
;
}
error
=
regulator_enable
(
data
->
vcc
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"Failed to enable regulator: %d
\n
"
,
error
);
return
error
;
}
error
=
devm_add_action
(
&
client
->
dev
,
elan_disable_regulator
,
data
);
if
(
error
)
{
regulator_disable
(
data
->
vcc
);
dev_err
(
&
client
->
dev
,
"Failed to add disable regulator action: %d
\n
"
,
error
);
return
error
;
}
/* Initialize the touchpad. */
error
=
elan_initialize
(
data
);
if
(
error
)
return
error
;
error
=
elan_query_device_info
(
data
);
if
(
error
)
return
error
;
error
=
elan_query_device_parameters
(
data
);
if
(
error
)
return
error
;
dev_dbg
(
&
client
->
dev
,
"Elan Touchpad Information:
\n
"
" Module product ID: 0x%04x
\n
"
" Firmware Version: 0x%04x
\n
"
" Sample Version: 0x%04x
\n
"
" IAP Version: 0x%04x
\n
"
" Max ABS X,Y: %d,%d
\n
"
" Width X,Y: %d,%d
\n
"
" Resolution X,Y: %d,%d (dots/mm)
\n
"
,
data
->
product_id
,
data
->
fw_version
,
data
->
sm_version
,
data
->
iap_version
,
data
->
max_x
,
data
->
max_y
,
data
->
width_x
,
data
->
width_y
,
data
->
x_res
,
data
->
y_res
);
/* Set up input device properties based on queried parameters. */
error
=
elan_setup_input_device
(
data
);
if
(
error
)
return
error
;
/*
* Systems using device tree should set up interrupt via DTS,
* the rest will use the default falling edge interrupts.
*/
irqflags
=
client
->
dev
.
of_node
?
0
:
IRQF_TRIGGER_FALLING
;
error
=
devm_request_threaded_irq
(
&
client
->
dev
,
client
->
irq
,
NULL
,
elan_isr
,
irqflags
|
IRQF_ONESHOT
,
client
->
name
,
data
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"cannot register irq=%d
\n
"
,
client
->
irq
);
return
error
;
}
error
=
sysfs_create_groups
(
&
client
->
dev
.
kobj
,
elan_sysfs_groups
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"failed to create sysfs attributes: %d
\n
"
,
error
);
return
error
;
}
error
=
devm_add_action
(
&
client
->
dev
,
elan_remove_sysfs_groups
,
data
);
if
(
error
)
{
elan_remove_sysfs_groups
(
data
);
dev_err
(
&
client
->
dev
,
"Failed to add sysfs cleanup action: %d
\n
"
,
error
);
return
error
;
}
error
=
input_register_device
(
data
->
input
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"failed to register input device: %d
\n
"
,
error
);
return
error
;
}
/*
* Systems using device tree should set up wakeup via DTS,
* the rest will configure device as wakeup source by default.
*/
if
(
!
client
->
dev
.
of_node
)
device_init_wakeup
(
&
client
->
dev
,
true
);
return
0
;
}
static
int
__maybe_unused
elan_suspend
(
struct
device
*
dev
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elan_tp_data
*
data
=
i2c_get_clientdata
(
client
);
int
ret
;
/*
* We are taking the mutex to make sure sysfs operations are
* complete before we attempt to bring the device into low[er]
* power mode.
*/
ret
=
mutex_lock_interruptible
(
&
data
->
sysfs_mutex
);
if
(
ret
)
return
ret
;
disable_irq
(
client
->
irq
);
if
(
device_may_wakeup
(
dev
))
{
ret
=
elan_sleep
(
data
);
/* Enable wake from IRQ */
data
->
irq_wake
=
(
enable_irq_wake
(
client
->
irq
)
==
0
);
}
else
{
ret
=
elan_disable_power
(
data
);
}
mutex_unlock
(
&
data
->
sysfs_mutex
);
return
ret
;
}
static
int
__maybe_unused
elan_resume
(
struct
device
*
dev
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elan_tp_data
*
data
=
i2c_get_clientdata
(
client
);
int
error
;
if
(
device_may_wakeup
(
dev
)
&&
data
->
irq_wake
)
{
disable_irq_wake
(
client
->
irq
);
data
->
irq_wake
=
false
;
}
error
=
elan_enable_power
(
data
);
if
(
error
)
dev_err
(
dev
,
"power up when resuming failed: %d
\n
"
,
error
);
error
=
elan_initialize
(
data
);
if
(
error
)
dev_err
(
dev
,
"initialize when resuming failed: %d
\n
"
,
error
);
enable_irq
(
data
->
client
->
irq
);
return
0
;
}
static
SIMPLE_DEV_PM_OPS
(
elan_pm_ops
,
elan_suspend
,
elan_resume
);
static
const
struct
i2c_device_id
elan_id
[]
=
{
{
DRIVER_NAME
,
0
},
{
},
};
MODULE_DEVICE_TABLE
(
i2c
,
elan_id
);
#ifdef CONFIG_ACPI
static
const
struct
acpi_device_id
elan_acpi_id
[]
=
{
{
"ELAN0000"
,
0
},
{
}
};
MODULE_DEVICE_TABLE
(
acpi
,
elan_acpi_id
);
#endif
#ifdef CONFIG_OF
static
const
struct
of_device_id
elan_of_match
[]
=
{
{
.
compatible
=
"elan,ekth3000"
},
{
/* sentinel */
}
};
MODULE_DEVICE_TABLE
(
of
,
elan_of_match
);
#endif
static
struct
i2c_driver
elan_driver
=
{
.
driver
=
{
.
name
=
DRIVER_NAME
,
.
owner
=
THIS_MODULE
,
.
pm
=
&
elan_pm_ops
,
.
acpi_match_table
=
ACPI_PTR
(
elan_acpi_id
),
.
of_match_table
=
of_match_ptr
(
elan_of_match
),
},
.
probe
=
elan_probe
,
.
id_table
=
elan_id
,
};
module_i2c_driver
(
elan_driver
);
MODULE_AUTHOR
(
"Duson Lin <dusonlin@emc.com.tw>"
);
MODULE_DESCRIPTION
(
"Elan I2C/SMBus Touchpad driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_VERSION
(
ELAN_DRIVER_VERSION
);
drivers/input/mouse/elan_i2c_i2c.c
0 → 100644
浏览文件 @
f20c86cd
/*
* 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
,
};
drivers/input/mouse/elan_i2c_smbus.c
0 → 100644
浏览文件 @
f20c86cd
/*
* 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
,
};
drivers/input/mouse/lifebook.h
浏览文件 @
f20c86cd
...
@@ -16,14 +16,14 @@ void lifebook_module_init(void);
...
@@ -16,14 +16,14 @@ void lifebook_module_init(void);
int
lifebook_detect
(
struct
psmouse
*
psmouse
,
bool
set_properties
);
int
lifebook_detect
(
struct
psmouse
*
psmouse
,
bool
set_properties
);
int
lifebook_init
(
struct
psmouse
*
psmouse
);
int
lifebook_init
(
struct
psmouse
*
psmouse
);
#else
#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
;
return
-
ENOSYS
;
}
}
inline
int
lifebook_init
(
struct
psmouse
*
psmouse
)
static
inline
int
lifebook_init
(
struct
psmouse
*
psmouse
)
{
{
return
-
ENOSYS
;
return
-
ENOSYS
;
}
}
...
...
drivers/input/mouse/navpoint.c
浏览文件 @
f20c86cd
...
@@ -318,8 +318,7 @@ static int navpoint_remove(struct platform_device *pdev)
...
@@ -318,8 +318,7 @@ static int navpoint_remove(struct platform_device *pdev)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
navpoint_suspend
(
struct
device
*
dev
)
static
int
navpoint_suspend
(
struct
device
*
dev
)
{
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
navpoint
*
navpoint
=
platform_get_drvdata
(
pdev
);
struct
navpoint
*
navpoint
=
platform_get_drvdata
(
pdev
);
...
@@ -333,7 +332,7 @@ static int navpoint_suspend(struct device *dev)
...
@@ -333,7 +332,7 @@ static int navpoint_suspend(struct device *dev)
return
0
;
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
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
navpoint
*
navpoint
=
platform_get_drvdata
(
pdev
);
struct
navpoint
*
navpoint
=
platform_get_drvdata
(
pdev
);
...
@@ -346,7 +345,6 @@ static int navpoint_resume(struct device *dev)
...
@@ -346,7 +345,6 @@ static int navpoint_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
navpoint_pm_ops
,
navpoint_suspend
,
navpoint_resume
);
static
SIMPLE_DEV_PM_OPS
(
navpoint_pm_ops
,
navpoint_suspend
,
navpoint_resume
);
...
...
drivers/input/mouse/synaptics_i2c.c
浏览文件 @
f20c86cd
...
@@ -614,8 +614,7 @@ static int synaptics_i2c_remove(struct i2c_client *client)
...
@@ -614,8 +614,7 @@ static int synaptics_i2c_remove(struct i2c_client *client)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
synaptics_i2c_suspend
(
struct
device
*
dev
)
static
int
synaptics_i2c_suspend
(
struct
device
*
dev
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
synaptics_i2c
*
touch
=
i2c_get_clientdata
(
client
);
struct
synaptics_i2c
*
touch
=
i2c_get_clientdata
(
client
);
...
@@ -628,7 +627,7 @@ static int synaptics_i2c_suspend(struct device *dev)
...
@@ -628,7 +627,7 @@ static int synaptics_i2c_suspend(struct device *dev)
return
0
;
return
0
;
}
}
static
int
synaptics_i2c_resume
(
struct
device
*
dev
)
static
int
__maybe_unused
synaptics_i2c_resume
(
struct
device
*
dev
)
{
{
int
ret
;
int
ret
;
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
...
@@ -643,7 +642,6 @@ static int synaptics_i2c_resume(struct device *dev)
...
@@ -643,7 +642,6 @@ static int synaptics_i2c_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
synaptics_i2c_pm
,
synaptics_i2c_suspend
,
static
SIMPLE_DEV_PM_OPS
(
synaptics_i2c_pm
,
synaptics_i2c_suspend
,
synaptics_i2c_resume
);
synaptics_i2c_resume
);
...
...
drivers/input/serio/altera_ps2.c
浏览文件 @
f20c86cd
...
@@ -24,9 +24,7 @@
...
@@ -24,9 +24,7 @@
struct
ps2if
{
struct
ps2if
{
struct
serio
*
io
;
struct
serio
*
io
;
struct
resource
*
iomem_res
;
void
__iomem
*
base
;
void
__iomem
*
base
;
unsigned
irq
;
};
};
/*
/*
...
@@ -83,16 +81,34 @@ static void altera_ps2_close(struct serio *io)
...
@@ -83,16 +81,34 @@ static void altera_ps2_close(struct serio *io)
static
int
altera_ps2_probe
(
struct
platform_device
*
pdev
)
static
int
altera_ps2_probe
(
struct
platform_device
*
pdev
)
{
{
struct
ps2if
*
ps2if
;
struct
ps2if
*
ps2if
;
struct
resource
*
res
;
struct
serio
*
serio
;
struct
serio
*
serio
;
int
error
,
irq
;
int
error
,
irq
;
ps2if
=
kzalloc
(
sizeof
(
struct
ps2if
),
GFP_KERNEL
);
ps2if
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
struct
ps2if
),
GFP_KERNEL
);
serio
=
kzalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
!
ps2if
)
if
(
!
ps2if
||
!
serio
)
{
return
-
ENOMEM
;
error
=
-
ENOMEM
;
goto
err_free_mem
;
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
->
id
.
type
=
SERIO_8042
;
serio
->
write
=
altera_ps2_write
;
serio
->
write
=
altera_ps2_write
;
serio
->
open
=
altera_ps2_open
;
serio
->
open
=
altera_ps2_open
;
...
@@ -103,56 +119,12 @@ static int altera_ps2_probe(struct platform_device *pdev)
...
@@ -103,56 +119,12 @@ static int altera_ps2_probe(struct platform_device *pdev)
serio
->
dev
.
parent
=
&
pdev
->
dev
;
serio
->
dev
.
parent
=
&
pdev
->
dev
;
ps2if
->
io
=
serio
;
ps2if
->
io
=
serio
;
ps2if
->
iomem_res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
dev_info
(
&
pdev
->
dev
,
"base %p, irq %d
\n
"
,
ps2if
->
base
,
irq
);
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
);
serio_register_port
(
ps2if
->
io
);
serio_register_port
(
ps2if
->
io
);
platform_set_drvdata
(
pdev
,
ps2if
);
platform_set_drvdata
(
pdev
,
ps2if
);
return
0
;
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)
...
@@ -163,11 +135,6 @@ static int altera_ps2_remove(struct platform_device *pdev)
struct
ps2if
*
ps2if
=
platform_get_drvdata
(
pdev
);
struct
ps2if
*
ps2if
=
platform_get_drvdata
(
pdev
);
serio_unregister_port
(
ps2if
->
io
);
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
;
return
0
;
}
}
...
...
drivers/input/serio/i8042-x86ia64io.h
浏览文件 @
f20c86cd
...
@@ -578,6 +578,16 @@ static const struct dmi_system_id __initconst i8042_dmi_nopnp_table[] = {
...
@@ -578,6 +578,16 @@ static const struct dmi_system_id __initconst i8042_dmi_nopnp_table[] = {
DMI_MATCH
(
DMI_BOARD_VENDOR
,
"Intel Corporation"
),
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 */
/* MSI Wind U-100 */
.
matches
=
{
.
matches
=
{
...
...
drivers/input/serio/serio.c
浏览文件 @
f20c86cd
...
@@ -514,7 +514,7 @@ static void serio_release_port(struct device *dev)
...
@@ -514,7 +514,7 @@ static void serio_release_port(struct device *dev)
*/
*/
static
void
serio_init_port
(
struct
serio
*
serio
)
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
);
__module_get
(
THIS_MODULE
);
...
@@ -525,7 +525,7 @@ static void serio_init_port(struct serio *serio)
...
@@ -525,7 +525,7 @@ static void serio_init_port(struct serio *serio)
mutex_init
(
&
serio
->
drv_mutex
);
mutex_init
(
&
serio
->
drv_mutex
);
device_initialize
(
&
serio
->
dev
);
device_initialize
(
&
serio
->
dev
);
dev_set_name
(
&
serio
->
dev
,
"serio%lu"
,
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
.
bus
=
&
serio_bus
;
serio
->
dev
.
release
=
serio_release_port
;
serio
->
dev
.
release
=
serio_release_port
;
serio
->
dev
.
groups
=
serio_device_attr_groups
;
serio
->
dev
.
groups
=
serio_device_attr_groups
;
...
...
drivers/input/serio/serio_raw.c
浏览文件 @
f20c86cd
...
@@ -292,7 +292,7 @@ static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
...
@@ -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
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
;
struct
serio_raw
*
serio_raw
;
int
err
;
int
err
;
...
@@ -303,7 +303,7 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
...
@@ -303,7 +303,7 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
}
}
snprintf
(
serio_raw
->
name
,
sizeof
(
serio_raw
->
name
),
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
);
kref_init
(
&
serio_raw
->
kref
);
INIT_LIST_HEAD
(
&
serio_raw
->
client_list
);
INIT_LIST_HEAD
(
&
serio_raw
->
client_list
);
init_waitqueue_head
(
&
serio_raw
->
wait
);
init_waitqueue_head
(
&
serio_raw
->
wait
);
...
...
drivers/input/touchscreen/Kconfig
浏览文件 @
f20c86cd
...
@@ -295,6 +295,19 @@ config TOUCHSCREEN_FUJITSU
...
@@ -295,6 +295,19 @@ config TOUCHSCREEN_FUJITSU
To compile this driver as a module, choose M here: the
To compile this driver as a module, choose M here: the
module will be called fujitsu-ts.
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
config TOUCHSCREEN_ILI210X
tristate "Ilitek ILI210X based touchscreen"
tristate "Ilitek ILI210X based touchscreen"
depends on I2C
depends on I2C
...
@@ -334,6 +347,18 @@ config TOUCHSCREEN_GUNZE
...
@@ -334,6 +347,18 @@ config TOUCHSCREEN_GUNZE
To compile this driver as a module, choose M here: the
To compile this driver as a module, choose M here: the
module will be called gunze.
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
config TOUCHSCREEN_ELO
tristate "Elo serial touchscreens"
tristate "Elo serial touchscreens"
select SERIO
select SERIO
...
...
drivers/input/touchscreen/Makefile
浏览文件 @
f20c86cd
...
@@ -31,9 +31,11 @@ obj-$(CONFIG_TOUCHSCREEN_EDT_FT5X06) += edt-ft5x06.o
...
@@ -31,9 +31,11 @@ obj-$(CONFIG_TOUCHSCREEN_EDT_FT5X06) += edt-ft5x06.o
obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE)
+=
hampshire.o
obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE)
+=
hampshire.o
obj-$(CONFIG_TOUCHSCREEN_GUNZE)
+=
gunze.o
obj-$(CONFIG_TOUCHSCREEN_GUNZE)
+=
gunze.o
obj-$(CONFIG_TOUCHSCREEN_EETI)
+=
eeti_ts.o
obj-$(CONFIG_TOUCHSCREEN_EETI)
+=
eeti_ts.o
obj-$(CONFIG_TOUCHSCREEN_ELAN)
+=
elants_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ELO)
+=
elo.o
obj-$(CONFIG_TOUCHSCREEN_ELO)
+=
elo.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX)
+=
egalax_ts.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX)
+=
egalax_ts.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU)
+=
fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU)
+=
fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX)
+=
goodix.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X)
+=
ili210x.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X)
+=
ili210x.o
obj-$(CONFIG_TOUCHSCREEN_INEXIO)
+=
inexio.o
obj-$(CONFIG_TOUCHSCREEN_INEXIO)
+=
inexio.o
obj-$(CONFIG_TOUCHSCREEN_INTEL_MID)
+=
intel-mid-touch.o
obj-$(CONFIG_TOUCHSCREEN_INTEL_MID)
+=
intel-mid-touch.o
...
...
drivers/input/touchscreen/ad7877.c
浏览文件 @
f20c86cd
...
@@ -820,8 +820,7 @@ static int ad7877_remove(struct spi_device *spi)
...
@@ -820,8 +820,7 @@ static int ad7877_remove(struct spi_device *spi)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
ad7877_suspend
(
struct
device
*
dev
)
static
int
ad7877_suspend
(
struct
device
*
dev
)
{
{
struct
ad7877
*
ts
=
dev_get_drvdata
(
dev
);
struct
ad7877
*
ts
=
dev_get_drvdata
(
dev
);
...
@@ -830,7 +829,7 @@ static int ad7877_suspend(struct device *dev)
...
@@ -830,7 +829,7 @@ static int ad7877_suspend(struct device *dev)
return
0
;
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
);
struct
ad7877
*
ts
=
dev_get_drvdata
(
dev
);
...
@@ -838,7 +837,6 @@ static int ad7877_resume(struct device *dev)
...
@@ -838,7 +837,6 @@ static int ad7877_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
ad7877_pm
,
ad7877_suspend
,
ad7877_resume
);
static
SIMPLE_DEV_PM_OPS
(
ad7877_pm
,
ad7877_suspend
,
ad7877_resume
);
...
...
drivers/input/touchscreen/ad7879.c
浏览文件 @
f20c86cd
...
@@ -284,8 +284,7 @@ static void ad7879_close(struct input_dev* input)
...
@@ -284,8 +284,7 @@ static void ad7879_close(struct input_dev* input)
__ad7879_disable
(
ts
);
__ad7879_disable
(
ts
);
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
ad7879_suspend
(
struct
device
*
dev
)
static
int
ad7879_suspend
(
struct
device
*
dev
)
{
{
struct
ad7879
*
ts
=
dev_get_drvdata
(
dev
);
struct
ad7879
*
ts
=
dev_get_drvdata
(
dev
);
...
@@ -301,7 +300,7 @@ static int ad7879_suspend(struct device *dev)
...
@@ -301,7 +300,7 @@ static int ad7879_suspend(struct device *dev)
return
0
;
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
);
struct
ad7879
*
ts
=
dev_get_drvdata
(
dev
);
...
@@ -316,7 +315,6 @@ static int ad7879_resume(struct device *dev)
...
@@ -316,7 +315,6 @@ static int ad7879_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
SIMPLE_DEV_PM_OPS
(
ad7879_pm_ops
,
ad7879_suspend
,
ad7879_resume
);
SIMPLE_DEV_PM_OPS
(
ad7879_pm_ops
,
ad7879_suspend
,
ad7879_resume
);
EXPORT_SYMBOL
(
ad7879_pm_ops
);
EXPORT_SYMBOL
(
ad7879_pm_ops
);
...
...
drivers/input/touchscreen/ads7846.c
浏览文件 @
f20c86cd
...
@@ -883,8 +883,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle)
...
@@ -883,8 +883,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle)
return
IRQ_HANDLED
;
return
IRQ_HANDLED
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
ads7846_suspend
(
struct
device
*
dev
)
static
int
ads7846_suspend
(
struct
device
*
dev
)
{
{
struct
ads7846
*
ts
=
dev_get_drvdata
(
dev
);
struct
ads7846
*
ts
=
dev_get_drvdata
(
dev
);
...
@@ -906,7 +905,7 @@ static int ads7846_suspend(struct device *dev)
...
@@ -906,7 +905,7 @@ static int ads7846_suspend(struct device *dev)
return
0
;
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
);
struct
ads7846
*
ts
=
dev_get_drvdata
(
dev
);
...
@@ -927,7 +926,6 @@ static int ads7846_resume(struct device *dev)
...
@@ -927,7 +926,6 @@ static int ads7846_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
ads7846_pm
,
ads7846_suspend
,
ads7846_resume
);
static
SIMPLE_DEV_PM_OPS
(
ads7846_pm
,
ads7846_suspend
,
ads7846_resume
);
...
...
drivers/input/touchscreen/atmel_mxt_ts.c
浏览文件 @
f20c86cd
...
@@ -2244,8 +2244,7 @@ static int mxt_remove(struct i2c_client *client)
...
@@ -2244,8 +2244,7 @@ static int mxt_remove(struct i2c_client *client)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
mxt_suspend
(
struct
device
*
dev
)
static
int
mxt_suspend
(
struct
device
*
dev
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
mxt_data
*
data
=
i2c_get_clientdata
(
client
);
struct
mxt_data
*
data
=
i2c_get_clientdata
(
client
);
...
@@ -2261,7 +2260,7 @@ static int mxt_suspend(struct device *dev)
...
@@ -2261,7 +2260,7 @@ static int mxt_suspend(struct device *dev)
return
0
;
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
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
mxt_data
*
data
=
i2c_get_clientdata
(
client
);
struct
mxt_data
*
data
=
i2c_get_clientdata
(
client
);
...
@@ -2276,7 +2275,6 @@ static int mxt_resume(struct device *dev)
...
@@ -2276,7 +2275,6 @@ static int mxt_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
mxt_pm_ops
,
mxt_suspend
,
mxt_resume
);
static
SIMPLE_DEV_PM_OPS
(
mxt_pm_ops
,
mxt_suspend
,
mxt_resume
);
...
...
drivers/input/touchscreen/auo-pixcir-ts.c
浏览文件 @
f20c86cd
...
@@ -417,8 +417,7 @@ static void auo_pixcir_input_close(struct input_dev *dev)
...
@@ -417,8 +417,7 @@ static void auo_pixcir_input_close(struct input_dev *dev)
return
;
return
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
auo_pixcir_suspend
(
struct
device
*
dev
)
static
int
auo_pixcir_suspend
(
struct
device
*
dev
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
auo_pixcir_ts
*
ts
=
i2c_get_clientdata
(
client
);
struct
auo_pixcir_ts
*
ts
=
i2c_get_clientdata
(
client
);
...
@@ -450,7 +449,7 @@ static int auo_pixcir_suspend(struct device *dev)
...
@@ -450,7 +449,7 @@ static int auo_pixcir_suspend(struct device *dev)
return
ret
;
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
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
auo_pixcir_ts
*
ts
=
i2c_get_clientdata
(
client
);
struct
auo_pixcir_ts
*
ts
=
i2c_get_clientdata
(
client
);
...
@@ -479,7 +478,6 @@ static int auo_pixcir_resume(struct device *dev)
...
@@ -479,7 +478,6 @@ static int auo_pixcir_resume(struct device *dev)
return
ret
;
return
ret
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
auo_pixcir_pm_ops
,
static
SIMPLE_DEV_PM_OPS
(
auo_pixcir_pm_ops
,
auo_pixcir_suspend
,
auo_pixcir_resume
);
auo_pixcir_suspend
,
auo_pixcir_resume
);
...
...
drivers/input/touchscreen/cy8ctmg110_ts.c
浏览文件 @
f20c86cd
...
@@ -291,8 +291,7 @@ static int cy8ctmg110_probe(struct i2c_client *client,
...
@@ -291,8 +291,7 @@ static int cy8ctmg110_probe(struct i2c_client *client,
return
err
;
return
err
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
cy8ctmg110_suspend
(
struct
device
*
dev
)
static
int
cy8ctmg110_suspend
(
struct
device
*
dev
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
cy8ctmg110
*
ts
=
i2c_get_clientdata
(
client
);
struct
cy8ctmg110
*
ts
=
i2c_get_clientdata
(
client
);
...
@@ -306,7 +305,7 @@ static int cy8ctmg110_suspend(struct device *dev)
...
@@ -306,7 +305,7 @@ static int cy8ctmg110_suspend(struct device *dev)
return
0
;
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
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
cy8ctmg110
*
ts
=
i2c_get_clientdata
(
client
);
struct
cy8ctmg110
*
ts
=
i2c_get_clientdata
(
client
);
...
@@ -319,7 +318,6 @@ static int cy8ctmg110_resume(struct device *dev)
...
@@ -319,7 +318,6 @@ static int cy8ctmg110_resume(struct device *dev)
}
}
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
cy8ctmg110_pm
,
cy8ctmg110_suspend
,
cy8ctmg110_resume
);
static
SIMPLE_DEV_PM_OPS
(
cy8ctmg110_pm
,
cy8ctmg110_suspend
,
cy8ctmg110_resume
);
...
...
drivers/input/touchscreen/cyttsp_core.c
浏览文件 @
f20c86cd
...
@@ -472,8 +472,7 @@ static int cyttsp_disable(struct cyttsp *ts)
...
@@ -472,8 +472,7 @@ static int cyttsp_disable(struct cyttsp *ts)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
cyttsp_suspend
(
struct
device
*
dev
)
static
int
cyttsp_suspend
(
struct
device
*
dev
)
{
{
struct
cyttsp
*
ts
=
dev_get_drvdata
(
dev
);
struct
cyttsp
*
ts
=
dev_get_drvdata
(
dev
);
int
retval
=
0
;
int
retval
=
0
;
...
@@ -491,7 +490,7 @@ static int cyttsp_suspend(struct device *dev)
...
@@ -491,7 +490,7 @@ static int cyttsp_suspend(struct device *dev)
return
retval
;
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
);
struct
cyttsp
*
ts
=
dev_get_drvdata
(
dev
);
...
@@ -507,8 +506,6 @@ static int cyttsp_resume(struct device *dev)
...
@@ -507,8 +506,6 @@ static int cyttsp_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
SIMPLE_DEV_PM_OPS
(
cyttsp_pm_ops
,
cyttsp_suspend
,
cyttsp_resume
);
SIMPLE_DEV_PM_OPS
(
cyttsp_pm_ops
,
cyttsp_suspend
,
cyttsp_resume
);
EXPORT_SYMBOL_GPL
(
cyttsp_pm_ops
);
EXPORT_SYMBOL_GPL
(
cyttsp_pm_ops
);
...
...
drivers/input/touchscreen/edt-ft5x06.c
浏览文件 @
f20c86cd
...
@@ -1092,8 +1092,7 @@ static int edt_ft5x06_ts_remove(struct i2c_client *client)
...
@@ -1092,8 +1092,7 @@ static int edt_ft5x06_ts_remove(struct i2c_client *client)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
edt_ft5x06_ts_suspend
(
struct
device
*
dev
)
static
int
edt_ft5x06_ts_suspend
(
struct
device
*
dev
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
...
@@ -1103,7 +1102,7 @@ static int edt_ft5x06_ts_suspend(struct device *dev)
...
@@ -1103,7 +1102,7 @@ static int edt_ft5x06_ts_suspend(struct device *dev)
return
0
;
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
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
...
@@ -1112,7 +1111,6 @@ static int edt_ft5x06_ts_resume(struct device *dev)
...
@@ -1112,7 +1111,6 @@ static int edt_ft5x06_ts_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
edt_ft5x06_ts_pm_ops
,
static
SIMPLE_DEV_PM_OPS
(
edt_ft5x06_ts_pm_ops
,
edt_ft5x06_ts_suspend
,
edt_ft5x06_ts_resume
);
edt_ft5x06_ts_suspend
,
edt_ft5x06_ts_resume
);
...
...
drivers/input/touchscreen/eeti_ts.c
浏览文件 @
f20c86cd
...
@@ -264,8 +264,7 @@ static int eeti_ts_remove(struct i2c_client *client)
...
@@ -264,8 +264,7 @@ static int eeti_ts_remove(struct i2c_client *client)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
eeti_ts_suspend
(
struct
device
*
dev
)
static
int
eeti_ts_suspend
(
struct
device
*
dev
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
eeti_ts_priv
*
priv
=
i2c_get_clientdata
(
client
);
struct
eeti_ts_priv
*
priv
=
i2c_get_clientdata
(
client
);
...
@@ -284,7 +283,7 @@ static int eeti_ts_suspend(struct device *dev)
...
@@ -284,7 +283,7 @@ static int eeti_ts_suspend(struct device *dev)
return
0
;
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
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
eeti_ts_priv
*
priv
=
i2c_get_clientdata
(
client
);
struct
eeti_ts_priv
*
priv
=
i2c_get_clientdata
(
client
);
...
@@ -302,7 +301,6 @@ static int eeti_ts_resume(struct device *dev)
...
@@ -302,7 +301,6 @@ static int eeti_ts_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
eeti_ts_pm
,
eeti_ts_suspend
,
eeti_ts_resume
);
static
SIMPLE_DEV_PM_OPS
(
eeti_ts_pm
,
eeti_ts_suspend
,
eeti_ts_resume
);
...
...
drivers/input/touchscreen/egalax_ts.c
浏览文件 @
f20c86cd
...
@@ -239,8 +239,7 @@ static const struct i2c_device_id egalax_ts_id[] = {
...
@@ -239,8 +239,7 @@ static const struct i2c_device_id egalax_ts_id[] = {
};
};
MODULE_DEVICE_TABLE
(
i2c
,
egalax_ts_id
);
MODULE_DEVICE_TABLE
(
i2c
,
egalax_ts_id
);
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
egalax_ts_suspend
(
struct
device
*
dev
)
static
int
egalax_ts_suspend
(
struct
device
*
dev
)
{
{
static
const
u8
suspend_cmd
[
MAX_I2C_DATA_LEN
]
=
{
static
const
u8
suspend_cmd
[
MAX_I2C_DATA_LEN
]
=
{
0x3
,
0x6
,
0xa
,
0x3
,
0x36
,
0x3f
,
0x2
,
0
,
0
,
0
0x3
,
0x6
,
0xa
,
0x3
,
0x36
,
0x3f
,
0x2
,
0
,
0
,
0
...
@@ -252,13 +251,12 @@ static int egalax_ts_suspend(struct device *dev)
...
@@ -252,13 +251,12 @@ static int egalax_ts_suspend(struct device *dev)
return
ret
>
0
?
0
:
ret
;
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
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
return
egalax_wake_up_device
(
client
);
return
egalax_wake_up_device
(
client
);
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
egalax_ts_pm_ops
,
egalax_ts_suspend
,
egalax_ts_resume
);
static
SIMPLE_DEV_PM_OPS
(
egalax_ts_pm_ops
,
egalax_ts_suspend
,
egalax_ts_resume
);
...
...
drivers/input/touchscreen/elants_i2c.c
0 → 100644
浏览文件 @
f20c86cd
/*
* Elan Microelectronics touch panels with I2C interface
*
* Copyright (C) 2014 Elan Microelectronics Corporation.
* Scott Liu <scott.liu@emc.com.tw>
*
* This code is partly based on hid-multitouch.c:
*
* Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr>
* Copyright (c) 2010-2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
* Copyright (c) 2010-2012 Ecole Nationale de l'Aviation Civile, France
*
*
* This code is partly based on i2c-hid.c:
*
* Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
* Copyright (c) 2012 Ecole Nationale de l'Aviation Civile, France
* Copyright (c) 2012 Red Hat, Inc
*/
/*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*/
#include <linux/module.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/async.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
#include <linux/buffer_head.h>
#include <linux/version.h>
#include <linux/slab.h>
#include <linux/firmware.h>
#include <linux/version.h>
#include <linux/input/mt.h>
#include <linux/acpi.h>
#include <linux/of.h>
#include <asm/unaligned.h>
/* Device, Driver information */
#define DEVICE_NAME "elants_i2c"
#define DRV_VERSION "1.0.9"
/* Convert from rows or columns into resolution */
#define ELAN_TS_RESOLUTION(n, m) (((n) - 1) * (m))
/* FW header data */
#define HEADER_SIZE 4
#define FW_HDR_TYPE 0
#define FW_HDR_COUNT 1
#define FW_HDR_LENGTH 2
/* Buffer mode Queue Header information */
#define QUEUE_HEADER_SINGLE 0x62
#define QUEUE_HEADER_NORMAL 0X63
#define QUEUE_HEADER_WAIT 0x64
/* Command header definition */
#define CMD_HEADER_WRITE 0x54
#define CMD_HEADER_READ 0x53
#define CMD_HEADER_6B_READ 0x5B
#define CMD_HEADER_RESP 0x52
#define CMD_HEADER_6B_RESP 0x9B
#define CMD_HEADER_HELLO 0x55
#define CMD_HEADER_REK 0x66
/* FW position data */
#define PACKET_SIZE 55
#define MAX_CONTACT_NUM 10
#define FW_POS_HEADER 0
#define FW_POS_STATE 1
#define FW_POS_TOTAL 2
#define FW_POS_XY 3
#define FW_POS_CHECKSUM 34
#define FW_POS_WIDTH 35
#define FW_POS_PRESSURE 45
#define HEADER_REPORT_10_FINGER 0x62
/* Header (4 bytes) plus 3 fill 10-finger packets */
#define MAX_PACKET_SIZE 169
#define BOOT_TIME_DELAY_MS 50
/* FW read command, 0x53 0x?? 0x0, 0x01 */
#define E_ELAN_INFO_FW_VER 0x00
#define E_ELAN_INFO_BC_VER 0x10
#define E_ELAN_INFO_TEST_VER 0xE0
#define E_ELAN_INFO_FW_ID 0xF0
#define E_INFO_OSR 0xD6
#define E_INFO_PHY_SCAN 0xD7
#define E_INFO_PHY_DRIVER 0xD8
#define MAX_RETRIES 3
#define MAX_FW_UPDATE_RETRIES 30
#define ELAN_FW_PAGESIZE 132
#define ELAN_FW_FILENAME "elants_i2c.bin"
/* calibration timeout definition */
#define ELAN_CALI_TIMEOUT_MSEC 10000
enum
elants_state
{
ELAN_STATE_NORMAL
,
ELAN_WAIT_QUEUE_HEADER
,
ELAN_WAIT_RECALIBRATION
,
};
enum
elants_iap_mode
{
ELAN_IAP_OPERATIONAL
,
ELAN_IAP_RECOVERY
,
};
/* struct elants_data - represents state of Elan touchscreen device */
struct
elants_data
{
struct
i2c_client
*
client
;
struct
input_dev
*
input
;
u16
fw_version
;
u8
test_version
;
u8
solution_version
;
u8
bc_version
;
u8
iap_version
;
u16
hw_version
;
unsigned
int
x_res
;
/* resolution in units/mm */
unsigned
int
y_res
;
unsigned
int
x_max
;
unsigned
int
y_max
;
enum
elants_state
state
;
enum
elants_iap_mode
iap_mode
;
/* Guards against concurrent access to the device via sysfs */
struct
mutex
sysfs_mutex
;
u8
cmd_resp
[
HEADER_SIZE
];
struct
completion
cmd_done
;
u8
buf
[
MAX_PACKET_SIZE
];
bool
wake_irq_enabled
;
};
static
int
elants_i2c_send
(
struct
i2c_client
*
client
,
const
void
*
data
,
size_t
size
)
{
int
ret
;
ret
=
i2c_master_send
(
client
,
data
,
size
);
if
(
ret
==
size
)
return
0
;
if
(
ret
>=
0
)
ret
=
-
EIO
;
dev_err
(
&
client
->
dev
,
"%s failed (%*ph): %d
\n
"
,
__func__
,
(
int
)
size
,
data
,
ret
);
return
ret
;
}
static
int
elants_i2c_read
(
struct
i2c_client
*
client
,
void
*
data
,
size_t
size
)
{
int
ret
;
ret
=
i2c_master_recv
(
client
,
data
,
size
);
if
(
ret
==
size
)
return
0
;
if
(
ret
>=
0
)
ret
=
-
EIO
;
dev_err
(
&
client
->
dev
,
"%s failed: %d
\n
"
,
__func__
,
ret
);
return
ret
;
}
static
int
elants_i2c_execute_command
(
struct
i2c_client
*
client
,
const
u8
*
cmd
,
size_t
cmd_size
,
u8
*
resp
,
size_t
resp_size
)
{
struct
i2c_msg
msgs
[
2
];
int
ret
;
u8
expected_response
;
switch
(
cmd
[
0
])
{
case
CMD_HEADER_READ
:
expected_response
=
CMD_HEADER_RESP
;
break
;
case
CMD_HEADER_6B_READ
:
expected_response
=
CMD_HEADER_6B_RESP
;
break
;
default:
dev_err
(
&
client
->
dev
,
"%s: invalid command %*ph
\n
"
,
__func__
,
(
int
)
cmd_size
,
cmd
);
return
-
EINVAL
;
}
msgs
[
0
].
addr
=
client
->
addr
;
msgs
[
0
].
flags
=
client
->
flags
&
I2C_M_TEN
;
msgs
[
0
].
len
=
cmd_size
;
msgs
[
0
].
buf
=
(
u8
*
)
cmd
;
msgs
[
1
].
addr
=
client
->
addr
;
msgs
[
1
].
flags
=
client
->
flags
&
I2C_M_TEN
;
msgs
[
1
].
flags
|=
I2C_M_RD
;
msgs
[
1
].
len
=
resp_size
;
msgs
[
1
].
buf
=
resp
;
ret
=
i2c_transfer
(
client
->
adapter
,
msgs
,
ARRAY_SIZE
(
msgs
));
if
(
ret
<
0
)
return
ret
;
if
(
ret
!=
ARRAY_SIZE
(
msgs
)
||
resp
[
FW_HDR_TYPE
]
!=
expected_response
)
return
-
EIO
;
return
0
;
}
static
int
elants_i2c_calibrate
(
struct
elants_data
*
ts
)
{
struct
i2c_client
*
client
=
ts
->
client
;
int
ret
,
error
;
static
const
u8
w_flashkey
[]
=
{
0x54
,
0xC0
,
0xE1
,
0x5A
};
static
const
u8
rek
[]
=
{
0x54
,
0x29
,
0x00
,
0x01
};
static
const
u8
rek_resp
[]
=
{
CMD_HEADER_REK
,
0x66
,
0x66
,
0x66
};
disable_irq
(
client
->
irq
);
ts
->
state
=
ELAN_WAIT_RECALIBRATION
;
reinit_completion
(
&
ts
->
cmd_done
);
elants_i2c_send
(
client
,
w_flashkey
,
sizeof
(
w_flashkey
));
elants_i2c_send
(
client
,
rek
,
sizeof
(
rek
));
enable_irq
(
client
->
irq
);
ret
=
wait_for_completion_interruptible_timeout
(
&
ts
->
cmd_done
,
msecs_to_jiffies
(
ELAN_CALI_TIMEOUT_MSEC
));
ts
->
state
=
ELAN_STATE_NORMAL
;
if
(
ret
<=
0
)
{
error
=
ret
<
0
?
ret
:
-
ETIMEDOUT
;
dev_err
(
&
client
->
dev
,
"error while waiting for calibration to complete: %d
\n
"
,
error
);
return
error
;
}
if
(
memcmp
(
rek_resp
,
ts
->
cmd_resp
,
sizeof
(
rek_resp
)))
{
dev_err
(
&
client
->
dev
,
"unexpected calibration response: %*ph
\n
"
,
(
int
)
sizeof
(
ts
->
cmd_resp
),
ts
->
cmd_resp
);
return
-
EINVAL
;
}
return
0
;
}
static
int
elants_i2c_sw_reset
(
struct
i2c_client
*
client
)
{
const
u8
soft_rst_cmd
[]
=
{
0x77
,
0x77
,
0x77
,
0x77
};
int
error
;
error
=
elants_i2c_send
(
client
,
soft_rst_cmd
,
sizeof
(
soft_rst_cmd
));
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"software reset failed: %d
\n
"
,
error
);
return
error
;
}
/*
* We should wait at least 10 msec (but no more than 40) before
* sending fastboot or IAP command to the device.
*/
msleep
(
30
);
return
0
;
}
static
u16
elants_i2c_parse_version
(
u8
*
buf
)
{
return
get_unaligned_be32
(
buf
)
>>
4
;
}
static
int
elants_i2c_query_fw_id
(
struct
elants_data
*
ts
)
{
struct
i2c_client
*
client
=
ts
->
client
;
int
error
,
retry_cnt
;
const
u8
cmd
[]
=
{
CMD_HEADER_READ
,
E_ELAN_INFO_FW_ID
,
0x00
,
0x01
};
u8
resp
[
HEADER_SIZE
];
for
(
retry_cnt
=
0
;
retry_cnt
<
MAX_RETRIES
;
retry_cnt
++
)
{
error
=
elants_i2c_execute_command
(
client
,
cmd
,
sizeof
(
cmd
),
resp
,
sizeof
(
resp
));
if
(
!
error
)
{
ts
->
hw_version
=
elants_i2c_parse_version
(
resp
);
if
(
ts
->
hw_version
!=
0xffff
)
return
0
;
}
dev_dbg
(
&
client
->
dev
,
"read fw id error=%d, buf=%*phC
\n
"
,
error
,
(
int
)
sizeof
(
resp
),
resp
);
}
dev_err
(
&
client
->
dev
,
"Failed to read fw id or fw id is invalid
\n
"
);
return
-
EINVAL
;
}
static
int
elants_i2c_query_fw_version
(
struct
elants_data
*
ts
)
{
struct
i2c_client
*
client
=
ts
->
client
;
int
error
,
retry_cnt
;
const
u8
cmd
[]
=
{
CMD_HEADER_READ
,
E_ELAN_INFO_FW_VER
,
0x00
,
0x01
};
u8
resp
[
HEADER_SIZE
];
for
(
retry_cnt
=
0
;
retry_cnt
<
MAX_RETRIES
;
retry_cnt
++
)
{
error
=
elants_i2c_execute_command
(
client
,
cmd
,
sizeof
(
cmd
),
resp
,
sizeof
(
resp
));
if
(
!
error
)
{
ts
->
fw_version
=
elants_i2c_parse_version
(
resp
);
if
(
ts
->
fw_version
!=
0x0000
&&
ts
->
fw_version
!=
0xffff
)
return
0
;
}
dev_dbg
(
&
client
->
dev
,
"read fw version error=%d, buf=%*phC
\n
"
,
error
,
(
int
)
sizeof
(
resp
),
resp
);
}
dev_err
(
&
client
->
dev
,
"Failed to read fw version or fw version is invalid
\n
"
);
return
-
EINVAL
;
}
static
int
elants_i2c_query_test_version
(
struct
elants_data
*
ts
)
{
struct
i2c_client
*
client
=
ts
->
client
;
int
error
,
retry_cnt
;
u16
version
;
const
u8
cmd
[]
=
{
CMD_HEADER_READ
,
E_ELAN_INFO_TEST_VER
,
0x00
,
0x01
};
u8
resp
[
HEADER_SIZE
];
for
(
retry_cnt
=
0
;
retry_cnt
<
MAX_RETRIES
;
retry_cnt
++
)
{
error
=
elants_i2c_execute_command
(
client
,
cmd
,
sizeof
(
cmd
),
resp
,
sizeof
(
resp
));
if
(
!
error
)
{
version
=
elants_i2c_parse_version
(
resp
);
ts
->
test_version
=
version
>>
8
;
ts
->
solution_version
=
version
&
0xff
;
return
0
;
}
dev_dbg
(
&
client
->
dev
,
"read test version error rc=%d, buf=%*phC
\n
"
,
error
,
(
int
)
sizeof
(
resp
),
resp
);
}
dev_err
(
&
client
->
dev
,
"Failed to read test version
\n
"
);
return
-
EINVAL
;
}
static
int
elants_i2c_query_bc_version
(
struct
elants_data
*
ts
)
{
struct
i2c_client
*
client
=
ts
->
client
;
const
u8
cmd
[]
=
{
CMD_HEADER_READ
,
E_ELAN_INFO_BC_VER
,
0x00
,
0x01
};
u8
resp
[
HEADER_SIZE
];
u16
version
;
int
error
;
error
=
elants_i2c_execute_command
(
client
,
cmd
,
sizeof
(
cmd
),
resp
,
sizeof
(
resp
));
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"read BC version error=%d, buf=%*phC
\n
"
,
error
,
(
int
)
sizeof
(
resp
),
resp
);
return
error
;
}
version
=
elants_i2c_parse_version
(
resp
);
ts
->
bc_version
=
version
>>
8
;
ts
->
iap_version
=
version
&
0xff
;
return
0
;
}
static
int
elants_i2c_query_ts_info
(
struct
elants_data
*
ts
)
{
struct
i2c_client
*
client
=
ts
->
client
;
int
error
;
u8
resp
[
17
];
u16
phy_x
,
phy_y
,
rows
,
cols
,
osr
;
const
u8
get_resolution_cmd
[]
=
{
CMD_HEADER_6B_READ
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
};
const
u8
get_osr_cmd
[]
=
{
CMD_HEADER_READ
,
E_INFO_OSR
,
0x00
,
0x01
};
const
u8
get_physical_scan_cmd
[]
=
{
CMD_HEADER_READ
,
E_INFO_PHY_SCAN
,
0x00
,
0x01
};
const
u8
get_physical_drive_cmd
[]
=
{
CMD_HEADER_READ
,
E_INFO_PHY_DRIVER
,
0x00
,
0x01
};
/* Get trace number */
error
=
elants_i2c_execute_command
(
client
,
get_resolution_cmd
,
sizeof
(
get_resolution_cmd
),
resp
,
sizeof
(
resp
));
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"get resolution command failed: %d
\n
"
,
error
);
return
error
;
}
rows
=
resp
[
2
]
+
resp
[
6
]
+
resp
[
10
];
cols
=
resp
[
3
]
+
resp
[
7
]
+
resp
[
11
];
/* Process mm_to_pixel information */
error
=
elants_i2c_execute_command
(
client
,
get_osr_cmd
,
sizeof
(
get_osr_cmd
),
resp
,
sizeof
(
resp
));
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"get osr command failed: %d
\n
"
,
error
);
return
error
;
}
osr
=
resp
[
3
];
error
=
elants_i2c_execute_command
(
client
,
get_physical_scan_cmd
,
sizeof
(
get_physical_scan_cmd
),
resp
,
sizeof
(
resp
));
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"get physical scan command failed: %d
\n
"
,
error
);
return
error
;
}
phy_x
=
get_unaligned_be16
(
&
resp
[
2
]);
error
=
elants_i2c_execute_command
(
client
,
get_physical_drive_cmd
,
sizeof
(
get_physical_drive_cmd
),
resp
,
sizeof
(
resp
));
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"get physical drive command failed: %d
\n
"
,
error
);
return
error
;
}
phy_y
=
get_unaligned_be16
(
&
resp
[
2
]);
dev_dbg
(
&
client
->
dev
,
"phy_x=%d, phy_y=%d
\n
"
,
phy_x
,
phy_y
);
if
(
rows
==
0
||
cols
==
0
||
osr
==
0
)
{
dev_warn
(
&
client
->
dev
,
"invalid trace number data: %d, %d, %d
\n
"
,
rows
,
cols
,
osr
);
}
else
{
/* translate trace number to TS resolution */
ts
->
x_max
=
ELAN_TS_RESOLUTION
(
rows
,
osr
);
ts
->
x_res
=
DIV_ROUND_CLOSEST
(
ts
->
x_max
,
phy_x
);
ts
->
y_max
=
ELAN_TS_RESOLUTION
(
cols
,
osr
);
ts
->
y_res
=
DIV_ROUND_CLOSEST
(
ts
->
y_max
,
phy_y
);
}
return
0
;
}
static
int
elants_i2c_fastboot
(
struct
i2c_client
*
client
)
{
const
u8
boot_cmd
[]
=
{
0x4D
,
0x61
,
0x69
,
0x6E
};
int
error
;
error
=
elants_i2c_send
(
client
,
boot_cmd
,
sizeof
(
boot_cmd
));
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"boot failed: %d
\n
"
,
error
);
return
error
;
}
dev_dbg
(
&
client
->
dev
,
"boot success -- 0x%x
\n
"
,
client
->
addr
);
return
0
;
}
static
int
elants_i2c_initialize
(
struct
elants_data
*
ts
)
{
struct
i2c_client
*
client
=
ts
->
client
;
int
error
,
retry_cnt
;
const
u8
hello_packet
[]
=
{
0x55
,
0x55
,
0x55
,
0x55
};
const
u8
recov_packet
[]
=
{
0x55
,
0x55
,
0x80
,
0x80
};
u8
buf
[
HEADER_SIZE
];
for
(
retry_cnt
=
0
;
retry_cnt
<
MAX_RETRIES
;
retry_cnt
++
)
{
error
=
elants_i2c_sw_reset
(
client
);
if
(
error
)
{
/* Continue initializing if it's the last try */
if
(
retry_cnt
<
MAX_RETRIES
-
1
)
continue
;
}
error
=
elants_i2c_fastboot
(
client
);
if
(
error
)
{
/* Continue initializing if it's the last try */
if
(
retry_cnt
<
MAX_RETRIES
-
1
)
continue
;
}
/* Wait for Hello packet */
msleep
(
BOOT_TIME_DELAY_MS
);
error
=
elants_i2c_read
(
client
,
buf
,
sizeof
(
buf
));
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"failed to read 'hello' packet: %d
\n
"
,
error
);
}
else
if
(
!
memcmp
(
buf
,
hello_packet
,
sizeof
(
hello_packet
)))
{
ts
->
iap_mode
=
ELAN_IAP_OPERATIONAL
;
break
;
}
else
if
(
!
memcmp
(
buf
,
recov_packet
,
sizeof
(
recov_packet
)))
{
/*
* Setting error code will mark device
* in recovery mode below.
*/
error
=
-
EIO
;
break
;
}
else
{
error
=
-
EINVAL
;
dev_err
(
&
client
->
dev
,
"invalid 'hello' packet: %*ph
\n
"
,
(
int
)
sizeof
(
buf
),
buf
);
}
}
if
(
!
error
)
error
=
elants_i2c_query_fw_id
(
ts
);
if
(
!
error
)
error
=
elants_i2c_query_fw_version
(
ts
);
if
(
error
)
{
ts
->
iap_mode
=
ELAN_IAP_RECOVERY
;
}
else
{
elants_i2c_query_test_version
(
ts
);
elants_i2c_query_bc_version
(
ts
);
elants_i2c_query_ts_info
(
ts
);
}
return
0
;
}
/*
* Firmware update interface.
*/
static
int
elants_i2c_fw_write_page
(
struct
i2c_client
*
client
,
const
void
*
page
)
{
const
u8
ack_ok
[]
=
{
0xaa
,
0xaa
};
u8
buf
[
2
];
int
retry
;
int
error
;
for
(
retry
=
0
;
retry
<
MAX_FW_UPDATE_RETRIES
;
retry
++
)
{
error
=
elants_i2c_send
(
client
,
page
,
ELAN_FW_PAGESIZE
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"IAP Write Page failed: %d
\n
"
,
error
);
continue
;
}
error
=
elants_i2c_read
(
client
,
buf
,
2
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"IAP Ack read failed: %d
\n
"
,
error
);
return
error
;
}
if
(
!
memcmp
(
buf
,
ack_ok
,
sizeof
(
ack_ok
)))
return
0
;
error
=
-
EIO
;
dev_err
(
&
client
->
dev
,
"IAP Get Ack Error [%02x:%02x]
\n
"
,
buf
[
0
],
buf
[
1
]);
}
return
error
;
}
static
int
elants_i2c_do_update_firmware
(
struct
i2c_client
*
client
,
const
struct
firmware
*
fw
,
bool
force
)
{
const
u8
enter_iap
[]
=
{
0x45
,
0x49
,
0x41
,
0x50
};
const
u8
enter_iap2
[]
=
{
0x54
,
0x00
,
0x12
,
0x34
};
const
u8
iap_ack
[]
=
{
0x55
,
0xaa
,
0x33
,
0xcc
};
u8
buf
[
HEADER_SIZE
];
u16
send_id
;
int
page
,
n_fw_pages
;
int
error
;
/* Recovery mode detection! */
if
(
force
)
{
dev_dbg
(
&
client
->
dev
,
"Recovery mode procedure
\n
"
);
error
=
elants_i2c_send
(
client
,
enter_iap2
,
sizeof
(
enter_iap2
));
}
else
{
/* Start IAP Procedure */
dev_dbg
(
&
client
->
dev
,
"Normal IAP procedure
\n
"
);
elants_i2c_sw_reset
(
client
);
error
=
elants_i2c_send
(
client
,
enter_iap
,
sizeof
(
enter_iap
));
}
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"failed to enter IAP mode: %d
\n
"
,
error
);
return
error
;
}
msleep
(
20
);
/* check IAP state */
error
=
elants_i2c_read
(
client
,
buf
,
4
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"failed to read IAP acknowledgement: %d
\n
"
,
error
);
return
error
;
}
if
(
memcmp
(
buf
,
iap_ack
,
sizeof
(
iap_ack
)))
{
dev_err
(
&
client
->
dev
,
"failed to enter IAP: %*ph (expected %*ph)
\n
"
,
(
int
)
sizeof
(
buf
),
buf
,
(
int
)
sizeof
(
iap_ack
),
iap_ack
);
return
-
EIO
;
}
dev_info
(
&
client
->
dev
,
"successfully entered IAP mode"
);
send_id
=
client
->
addr
;
error
=
elants_i2c_send
(
client
,
&
send_id
,
1
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"sending dummy byte failed: %d
\n
"
,
error
);
return
error
;
}
/* Clear the last page of Master */
error
=
elants_i2c_send
(
client
,
fw
->
data
,
ELAN_FW_PAGESIZE
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"clearing of the last page failed: %d
\n
"
,
error
);
return
error
;
}
error
=
elants_i2c_read
(
client
,
buf
,
2
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"failed to read ACK for clearing the last page: %d
\n
"
,
error
);
return
error
;
}
n_fw_pages
=
fw
->
size
/
ELAN_FW_PAGESIZE
;
dev_dbg
(
&
client
->
dev
,
"IAP Pages = %d
\n
"
,
n_fw_pages
);
for
(
page
=
0
;
page
<
n_fw_pages
;
page
++
)
{
error
=
elants_i2c_fw_write_page
(
client
,
fw
->
data
+
page
*
ELAN_FW_PAGESIZE
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"failed to write FW page %d: %d
\n
"
,
page
,
error
);
return
error
;
}
}
/* Old iap needs to wait 200ms for WDT and rest is for hello packets */
msleep
(
300
);
dev_info
(
&
client
->
dev
,
"firmware update completed
\n
"
);
return
0
;
}
static
int
elants_i2c_fw_update
(
struct
elants_data
*
ts
)
{
struct
i2c_client
*
client
=
ts
->
client
;
const
struct
firmware
*
fw
;
int
error
;
error
=
request_firmware
(
&
fw
,
ELAN_FW_FILENAME
,
&
client
->
dev
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"failed to request firmware %s: %d
\n
"
,
ELAN_FW_FILENAME
,
error
);
return
error
;
}
if
(
fw
->
size
%
ELAN_FW_PAGESIZE
)
{
dev_err
(
&
client
->
dev
,
"invalid firmware length: %zu
\n
"
,
fw
->
size
);
error
=
-
EINVAL
;
goto
out
;
}
disable_irq
(
client
->
irq
);
error
=
elants_i2c_do_update_firmware
(
client
,
fw
,
ts
->
iap_mode
==
ELAN_IAP_RECOVERY
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"firmware update failed: %d
\n
"
,
error
);
ts
->
iap_mode
=
ELAN_IAP_RECOVERY
;
goto
out_enable_irq
;
}
error
=
elants_i2c_initialize
(
ts
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"failed to initialize device after firmware update: %d
\n
"
,
error
);
ts
->
iap_mode
=
ELAN_IAP_RECOVERY
;
goto
out_enable_irq
;
}
ts
->
iap_mode
=
ELAN_IAP_OPERATIONAL
;
out_enable_irq:
ts
->
state
=
ELAN_STATE_NORMAL
;
enable_irq
(
client
->
irq
);
msleep
(
100
);
if
(
!
error
)
elants_i2c_calibrate
(
ts
);
out:
release_firmware
(
fw
);
return
error
;
}
/*
* Event reporting.
*/
static
void
elants_i2c_mt_event
(
struct
elants_data
*
ts
,
u8
*
buf
)
{
struct
input_dev
*
input
=
ts
->
input
;
unsigned
int
n_fingers
;
u16
finger_state
;
int
i
;
n_fingers
=
buf
[
FW_POS_STATE
+
1
]
&
0x0f
;
finger_state
=
((
buf
[
FW_POS_STATE
+
1
]
&
0x30
)
<<
4
)
|
buf
[
FW_POS_STATE
];
dev_dbg
(
&
ts
->
client
->
dev
,
"n_fingers: %u, state: %04x
\n
"
,
n_fingers
,
finger_state
);
for
(
i
=
0
;
i
<
MAX_CONTACT_NUM
&&
n_fingers
;
i
++
)
{
if
(
finger_state
&
1
)
{
unsigned
int
x
,
y
,
p
,
w
;
u8
*
pos
;
pos
=
&
buf
[
FW_POS_XY
+
i
*
3
];
x
=
(((
u16
)
pos
[
0
]
&
0xf0
)
<<
4
)
|
pos
[
1
];
y
=
(((
u16
)
pos
[
0
]
&
0x0f
)
<<
8
)
|
pos
[
2
];
p
=
buf
[
FW_POS_PRESSURE
+
i
];
w
=
buf
[
FW_POS_WIDTH
+
i
];
dev_dbg
(
&
ts
->
client
->
dev
,
"i=%d x=%d y=%d p=%d w=%d
\n
"
,
i
,
x
,
y
,
p
,
w
);
input_mt_slot
(
input
,
i
);
input_mt_report_slot_state
(
input
,
MT_TOOL_FINGER
,
true
);
input_event
(
input
,
EV_ABS
,
ABS_MT_POSITION_X
,
x
);
input_event
(
input
,
EV_ABS
,
ABS_MT_POSITION_Y
,
y
);
input_event
(
input
,
EV_ABS
,
ABS_MT_PRESSURE
,
p
);
input_event
(
input
,
EV_ABS
,
ABS_MT_TOUCH_MAJOR
,
w
);
n_fingers
--
;
}
finger_state
>>=
1
;
}
input_mt_sync_frame
(
input
);
input_sync
(
input
);
}
static
u8
elants_i2c_calculate_checksum
(
u8
*
buf
)
{
u8
checksum
=
0
;
u8
i
;
for
(
i
=
0
;
i
<
FW_POS_CHECKSUM
;
i
++
)
checksum
+=
buf
[
i
];
return
checksum
;
}
static
void
elants_i2c_event
(
struct
elants_data
*
ts
,
u8
*
buf
)
{
u8
checksum
=
elants_i2c_calculate_checksum
(
buf
);
if
(
unlikely
(
buf
[
FW_POS_CHECKSUM
]
!=
checksum
))
dev_warn
(
&
ts
->
client
->
dev
,
"%s: invalid checksum for packet %02x: %02x vs. %02x
\n
"
,
__func__
,
buf
[
FW_POS_HEADER
],
checksum
,
buf
[
FW_POS_CHECKSUM
]);
else
if
(
unlikely
(
buf
[
FW_POS_HEADER
]
!=
HEADER_REPORT_10_FINGER
))
dev_warn
(
&
ts
->
client
->
dev
,
"%s: unknown packet type: %02x
\n
"
,
__func__
,
buf
[
FW_POS_HEADER
]);
else
elants_i2c_mt_event
(
ts
,
buf
);
}
static
irqreturn_t
elants_i2c_irq
(
int
irq
,
void
*
_dev
)
{
const
u8
wait_packet
[]
=
{
0x64
,
0x64
,
0x64
,
0x64
};
struct
elants_data
*
ts
=
_dev
;
struct
i2c_client
*
client
=
ts
->
client
;
int
report_count
,
report_len
;
int
i
;
int
len
;
len
=
i2c_master_recv
(
client
,
ts
->
buf
,
sizeof
(
ts
->
buf
));
if
(
len
<
0
)
{
dev_err
(
&
client
->
dev
,
"%s: failed to read data: %d
\n
"
,
__func__
,
len
);
goto
out
;
}
dev_dbg
(
&
client
->
dev
,
"%s: packet %*ph
\n
"
,
__func__
,
HEADER_SIZE
,
ts
->
buf
);
switch
(
ts
->
state
)
{
case
ELAN_WAIT_RECALIBRATION
:
if
(
ts
->
buf
[
FW_HDR_TYPE
]
==
CMD_HEADER_REK
)
{
memcpy
(
ts
->
cmd_resp
,
ts
->
buf
,
sizeof
(
ts
->
cmd_resp
));
complete
(
&
ts
->
cmd_done
);
ts
->
state
=
ELAN_STATE_NORMAL
;
}
break
;
case
ELAN_WAIT_QUEUE_HEADER
:
if
(
ts
->
buf
[
FW_HDR_TYPE
]
!=
QUEUE_HEADER_NORMAL
)
break
;
ts
->
state
=
ELAN_STATE_NORMAL
;
/* fall through */
case
ELAN_STATE_NORMAL
:
switch
(
ts
->
buf
[
FW_HDR_TYPE
])
{
case
CMD_HEADER_HELLO
:
case
CMD_HEADER_RESP
:
case
CMD_HEADER_REK
:
break
;
case
QUEUE_HEADER_WAIT
:
if
(
memcmp
(
ts
->
buf
,
wait_packet
,
sizeof
(
wait_packet
)))
{
dev_err
(
&
client
->
dev
,
"invalid wait packet %*ph
\n
"
,
HEADER_SIZE
,
ts
->
buf
);
}
else
{
ts
->
state
=
ELAN_WAIT_QUEUE_HEADER
;
udelay
(
30
);
}
break
;
case
QUEUE_HEADER_SINGLE
:
elants_i2c_event
(
ts
,
&
ts
->
buf
[
HEADER_SIZE
]);
break
;
case
QUEUE_HEADER_NORMAL
:
report_count
=
ts
->
buf
[
FW_HDR_COUNT
];
if
(
report_count
>
3
)
{
dev_err
(
&
client
->
dev
,
"too large report count: %*ph
\n
"
,
HEADER_SIZE
,
ts
->
buf
);
break
;
}
report_len
=
ts
->
buf
[
FW_HDR_LENGTH
]
/
report_count
;
if
(
report_len
!=
PACKET_SIZE
)
{
dev_err
(
&
client
->
dev
,
"mismatching report length: %*ph
\n
"
,
HEADER_SIZE
,
ts
->
buf
);
break
;
}
for
(
i
=
0
;
i
<
report_count
;
i
++
)
{
u8
*
buf
=
ts
->
buf
+
HEADER_SIZE
+
i
*
PACKET_SIZE
;
elants_i2c_event
(
ts
,
buf
);
}
break
;
default:
dev_err
(
&
client
->
dev
,
"unknown packet %*ph
\n
"
,
HEADER_SIZE
,
ts
->
buf
);
break
;
}
break
;
}
out:
return
IRQ_HANDLED
;
}
/*
* sysfs interface
*/
static
ssize_t
calibrate_store
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elants_data
*
ts
=
i2c_get_clientdata
(
client
);
int
error
;
error
=
mutex_lock_interruptible
(
&
ts
->
sysfs_mutex
);
if
(
error
)
return
error
;
error
=
elants_i2c_calibrate
(
ts
);
mutex_unlock
(
&
ts
->
sysfs_mutex
);
return
error
?:
count
;
}
static
ssize_t
write_update_fw
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elants_data
*
ts
=
i2c_get_clientdata
(
client
);
int
error
;
error
=
mutex_lock_interruptible
(
&
ts
->
sysfs_mutex
);
if
(
error
)
return
error
;
error
=
elants_i2c_fw_update
(
ts
);
dev_dbg
(
dev
,
"firmware update result: %d
\n
"
,
error
);
mutex_unlock
(
&
ts
->
sysfs_mutex
);
return
error
?:
count
;
}
static
ssize_t
show_iap_mode
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elants_data
*
ts
=
i2c_get_clientdata
(
client
);
return
sprintf
(
buf
,
"%s
\n
"
,
ts
->
iap_mode
==
ELAN_IAP_OPERATIONAL
?
"Normal"
:
"Recovery"
);
}
static
DEVICE_ATTR
(
calibrate
,
S_IWUSR
,
NULL
,
calibrate_store
);
static
DEVICE_ATTR
(
iap_mode
,
S_IRUGO
,
show_iap_mode
,
NULL
);
static
DEVICE_ATTR
(
update_fw
,
S_IWUSR
,
NULL
,
write_update_fw
);
struct
elants_version_attribute
{
struct
device_attribute
dattr
;
size_t
field_offset
;
size_t
field_size
;
};
#define __ELANTS_FIELD_SIZE(_field) \
sizeof(((struct elants_data *)NULL)->_field)
#define __ELANTS_VERIFY_SIZE(_field) \
(BUILD_BUG_ON_ZERO(__ELANTS_FIELD_SIZE(_field) > 2) + \
__ELANTS_FIELD_SIZE(_field))
#define ELANTS_VERSION_ATTR(_field) \
struct elants_version_attribute elants_ver_attr_##_field = { \
.dattr = __ATTR(_field, S_IRUGO, \
elants_version_attribute_show, NULL), \
.field_offset = offsetof(struct elants_data, _field), \
.field_size = __ELANTS_VERIFY_SIZE(_field), \
}
static
ssize_t
elants_version_attribute_show
(
struct
device
*
dev
,
struct
device_attribute
*
dattr
,
char
*
buf
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elants_data
*
ts
=
i2c_get_clientdata
(
client
);
struct
elants_version_attribute
*
attr
=
container_of
(
dattr
,
struct
elants_version_attribute
,
dattr
);
u8
*
field
=
(
u8
*
)((
char
*
)
ts
+
attr
->
field_offset
);
unsigned
int
fmt_size
;
unsigned
int
val
;
if
(
attr
->
field_size
==
1
)
{
val
=
*
field
;
fmt_size
=
2
;
/* 2 HEX digits */
}
else
{
val
=
*
(
u16
*
)
field
;
fmt_size
=
4
;
/* 4 HEX digits */
}
return
sprintf
(
buf
,
"%0*x
\n
"
,
fmt_size
,
val
);
}
static
ELANTS_VERSION_ATTR
(
fw_version
);
static
ELANTS_VERSION_ATTR
(
hw_version
);
static
ELANTS_VERSION_ATTR
(
test_version
);
static
ELANTS_VERSION_ATTR
(
solution_version
);
static
ELANTS_VERSION_ATTR
(
bc_version
);
static
ELANTS_VERSION_ATTR
(
iap_version
);
static
struct
attribute
*
elants_attributes
[]
=
{
&
dev_attr_calibrate
.
attr
,
&
dev_attr_update_fw
.
attr
,
&
dev_attr_iap_mode
.
attr
,
&
elants_ver_attr_fw_version
.
dattr
.
attr
,
&
elants_ver_attr_hw_version
.
dattr
.
attr
,
&
elants_ver_attr_test_version
.
dattr
.
attr
,
&
elants_ver_attr_solution_version
.
dattr
.
attr
,
&
elants_ver_attr_bc_version
.
dattr
.
attr
,
&
elants_ver_attr_iap_version
.
dattr
.
attr
,
NULL
};
static
struct
attribute_group
elants_attribute_group
=
{
.
attrs
=
elants_attributes
,
};
static
void
elants_i2c_remove_sysfs_group
(
void
*
_data
)
{
struct
elants_data
*
ts
=
_data
;
sysfs_remove_group
(
&
ts
->
client
->
dev
.
kobj
,
&
elants_attribute_group
);
}
static
int
elants_i2c_probe
(
struct
i2c_client
*
client
,
const
struct
i2c_device_id
*
id
)
{
union
i2c_smbus_data
dummy
;
struct
elants_data
*
ts
;
unsigned
long
irqflags
;
int
error
;
if
(
!
i2c_check_functionality
(
client
->
adapter
,
I2C_FUNC_I2C
))
{
dev_err
(
&
client
->
dev
,
"%s: i2c check functionality error
\n
"
,
DEVICE_NAME
);
return
-
ENXIO
;
}
/* Make sure there is something at this address */
if
(
i2c_smbus_xfer
(
client
->
adapter
,
client
->
addr
,
0
,
I2C_SMBUS_READ
,
0
,
I2C_SMBUS_BYTE
,
&
dummy
)
<
0
)
{
dev_err
(
&
client
->
dev
,
"nothing at this address
\n
"
);
return
-
ENXIO
;
}
ts
=
devm_kzalloc
(
&
client
->
dev
,
sizeof
(
struct
elants_data
),
GFP_KERNEL
);
if
(
!
ts
)
return
-
ENOMEM
;
mutex_init
(
&
ts
->
sysfs_mutex
);
init_completion
(
&
ts
->
cmd_done
);
ts
->
client
=
client
;
i2c_set_clientdata
(
client
,
ts
);
error
=
elants_i2c_initialize
(
ts
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"failed to initialize: %d
\n
"
,
error
);
return
error
;
}
ts
->
input
=
devm_input_allocate_device
(
&
client
->
dev
);
if
(
!
ts
->
input
)
{
dev_err
(
&
client
->
dev
,
"Failed to allocate input device
\n
"
);
return
-
ENOMEM
;
}
ts
->
input
->
name
=
"Elan Touchscreen"
;
ts
->
input
->
id
.
bustype
=
BUS_I2C
;
__set_bit
(
BTN_TOUCH
,
ts
->
input
->
keybit
);
__set_bit
(
EV_ABS
,
ts
->
input
->
evbit
);
__set_bit
(
EV_KEY
,
ts
->
input
->
evbit
);
/* Single touch input params setup */
input_set_abs_params
(
ts
->
input
,
ABS_X
,
0
,
ts
->
x_max
,
0
,
0
);
input_set_abs_params
(
ts
->
input
,
ABS_Y
,
0
,
ts
->
y_max
,
0
,
0
);
input_set_abs_params
(
ts
->
input
,
ABS_PRESSURE
,
0
,
255
,
0
,
0
);
input_abs_set_res
(
ts
->
input
,
ABS_X
,
ts
->
x_res
);
input_abs_set_res
(
ts
->
input
,
ABS_Y
,
ts
->
y_res
);
/* Multitouch input params setup */
error
=
input_mt_init_slots
(
ts
->
input
,
MAX_CONTACT_NUM
,
INPUT_MT_DIRECT
|
INPUT_MT_DROP_UNUSED
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"failed to initialize MT slots: %d
\n
"
,
error
);
return
error
;
}
input_set_abs_params
(
ts
->
input
,
ABS_MT_POSITION_X
,
0
,
ts
->
x_max
,
0
,
0
);
input_set_abs_params
(
ts
->
input
,
ABS_MT_POSITION_Y
,
0
,
ts
->
y_max
,
0
,
0
);
input_set_abs_params
(
ts
->
input
,
ABS_MT_TOUCH_MAJOR
,
0
,
255
,
0
,
0
);
input_set_abs_params
(
ts
->
input
,
ABS_MT_PRESSURE
,
0
,
255
,
0
,
0
);
input_abs_set_res
(
ts
->
input
,
ABS_MT_POSITION_X
,
ts
->
x_res
);
input_abs_set_res
(
ts
->
input
,
ABS_MT_POSITION_Y
,
ts
->
y_res
);
input_set_drvdata
(
ts
->
input
,
ts
);
error
=
input_register_device
(
ts
->
input
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"unable to register input device: %d
\n
"
,
error
);
return
error
;
}
/*
* Systems using device tree should set up interrupt via DTS,
* the rest will use the default falling edge interrupts.
*/
irqflags
=
client
->
dev
.
of_node
?
0
:
IRQF_TRIGGER_FALLING
;
error
=
devm_request_threaded_irq
(
&
client
->
dev
,
client
->
irq
,
NULL
,
elants_i2c_irq
,
irqflags
|
IRQF_ONESHOT
,
client
->
name
,
ts
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"Failed to register interrupt
\n
"
);
return
error
;
}
/*
* Systems using device tree should set up wakeup via DTS,
* the rest will configure device as wakeup source by default.
*/
if
(
!
client
->
dev
.
of_node
)
device_init_wakeup
(
&
client
->
dev
,
true
);
error
=
sysfs_create_group
(
&
client
->
dev
.
kobj
,
&
elants_attribute_group
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"failed to create sysfs attributes: %d
\n
"
,
error
);
return
error
;
}
error
=
devm_add_action
(
&
client
->
dev
,
elants_i2c_remove_sysfs_group
,
ts
);
if
(
error
)
{
elants_i2c_remove_sysfs_group
(
ts
);
dev_err
(
&
client
->
dev
,
"Failed to add sysfs cleanup action: %d
\n
"
,
error
);
return
error
;
}
return
0
;
}
static
int
__maybe_unused
elants_i2c_suspend
(
struct
device
*
dev
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elants_data
*
ts
=
i2c_get_clientdata
(
client
);
const
u8
set_sleep_cmd
[]
=
{
0x54
,
0x50
,
0x00
,
0x01
};
int
retry_cnt
;
int
error
;
/* Command not support in IAP recovery mode */
if
(
ts
->
iap_mode
!=
ELAN_IAP_OPERATIONAL
)
return
-
EBUSY
;
disable_irq
(
client
->
irq
);
for
(
retry_cnt
=
0
;
retry_cnt
<
MAX_RETRIES
;
retry_cnt
++
)
{
error
=
elants_i2c_send
(
client
,
set_sleep_cmd
,
sizeof
(
set_sleep_cmd
));
if
(
!
error
)
break
;
dev_err
(
&
client
->
dev
,
"suspend command failed: %d
\n
"
,
error
);
}
if
(
device_may_wakeup
(
dev
))
ts
->
wake_irq_enabled
=
(
enable_irq_wake
(
client
->
irq
)
==
0
);
return
0
;
}
static
int
__maybe_unused
elants_i2c_resume
(
struct
device
*
dev
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
elants_data
*
ts
=
i2c_get_clientdata
(
client
);
const
u8
set_active_cmd
[]
=
{
0x54
,
0x58
,
0x00
,
0x01
};
int
retry_cnt
;
int
error
;
if
(
device_may_wakeup
(
dev
)
&&
ts
->
wake_irq_enabled
)
disable_irq_wake
(
client
->
irq
);
for
(
retry_cnt
=
0
;
retry_cnt
<
MAX_RETRIES
;
retry_cnt
++
)
{
error
=
elants_i2c_send
(
client
,
set_active_cmd
,
sizeof
(
set_active_cmd
));
if
(
!
error
)
break
;
dev_err
(
&
client
->
dev
,
"resume command failed: %d
\n
"
,
error
);
}
ts
->
state
=
ELAN_STATE_NORMAL
;
enable_irq
(
client
->
irq
);
return
0
;
}
static
SIMPLE_DEV_PM_OPS
(
elants_i2c_pm_ops
,
elants_i2c_suspend
,
elants_i2c_resume
);
static
const
struct
i2c_device_id
elants_i2c_id
[]
=
{
{
DEVICE_NAME
,
0
},
{
}
};
MODULE_DEVICE_TABLE
(
i2c
,
elants_i2c_id
);
#ifdef CONFIG_ACPI
static
const
struct
acpi_device_id
elants_acpi_id
[]
=
{
{
"ELAN0001"
,
0
},
{
}
};
MODULE_DEVICE_TABLE
(
acpi
,
elants_acpi_id
);
#endif
#ifdef CONFIG_OF
static
const
struct
of_device_id
elants_of_match
[]
=
{
{
.
compatible
=
"elan,ekth3500"
},
{
/* sentinel */
}
};
MODULE_DEVICE_TABLE
(
of
,
elants_of_match
);
#endif
static
struct
i2c_driver
elants_i2c_driver
=
{
.
probe
=
elants_i2c_probe
,
.
id_table
=
elants_i2c_id
,
.
driver
=
{
.
name
=
DEVICE_NAME
,
.
owner
=
THIS_MODULE
,
.
pm
=
&
elants_i2c_pm_ops
,
.
acpi_match_table
=
ACPI_PTR
(
elants_acpi_id
),
.
of_match_table
=
of_match_ptr
(
elants_of_match
),
},
};
module_i2c_driver
(
elants_i2c_driver
);
MODULE_AUTHOR
(
"Scott Liu <scott.liu@emc.com.tw>"
);
MODULE_DESCRIPTION
(
"Elan I2c Touchscreen driver"
);
MODULE_VERSION
(
DRV_VERSION
);
MODULE_LICENSE
(
"GPL"
);
drivers/input/touchscreen/goodix.c
0 → 100644
浏览文件 @
f20c86cd
/*
* 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"
);
drivers/input/touchscreen/ili210x.c
浏览文件 @
f20c86cd
...
@@ -311,8 +311,7 @@ static int ili210x_i2c_remove(struct i2c_client *client)
...
@@ -311,8 +311,7 @@ static int ili210x_i2c_remove(struct i2c_client *client)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
ili210x_i2c_suspend
(
struct
device
*
dev
)
static
int
ili210x_i2c_suspend
(
struct
device
*
dev
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
...
@@ -322,7 +321,7 @@ static int ili210x_i2c_suspend(struct device *dev)
...
@@ -322,7 +321,7 @@ static int ili210x_i2c_suspend(struct device *dev)
return
0
;
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
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
...
@@ -331,7 +330,6 @@ static int ili210x_i2c_resume(struct device *dev)
...
@@ -331,7 +330,6 @@ static int ili210x_i2c_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
ili210x_i2c_pm
,
static
SIMPLE_DEV_PM_OPS
(
ili210x_i2c_pm
,
ili210x_i2c_suspend
,
ili210x_i2c_resume
);
ili210x_i2c_suspend
,
ili210x_i2c_resume
);
...
...
drivers/input/touchscreen/ipaq-micro-ts.c
浏览文件 @
f20c86cd
...
@@ -122,8 +122,7 @@ static int micro_ts_probe(struct platform_device *pdev)
...
@@ -122,8 +122,7 @@ static int micro_ts_probe(struct platform_device *pdev)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
micro_ts_suspend
(
struct
device
*
dev
)
static
int
micro_ts_suspend
(
struct
device
*
dev
)
{
{
struct
touchscreen_data
*
ts
=
dev_get_drvdata
(
dev
);
struct
touchscreen_data
*
ts
=
dev_get_drvdata
(
dev
);
...
@@ -132,7 +131,7 @@ static int micro_ts_suspend(struct device *dev)
...
@@ -132,7 +131,7 @@ static int micro_ts_suspend(struct device *dev)
return
0
;
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
touchscreen_data
*
ts
=
dev_get_drvdata
(
dev
);
struct
input_dev
*
input
=
ts
->
input
;
struct
input_dev
*
input
=
ts
->
input
;
...
@@ -146,7 +145,6 @@ static int micro_ts_resume(struct device *dev)
...
@@ -146,7 +145,6 @@ static int micro_ts_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
const
struct
dev_pm_ops
micro_ts_dev_pm_ops
=
{
static
const
struct
dev_pm_ops
micro_ts_dev_pm_ops
=
{
SET_SYSTEM_SLEEP_PM_OPS
(
micro_ts_suspend
,
micro_ts_resume
)
SET_SYSTEM_SLEEP_PM_OPS
(
micro_ts_suspend
,
micro_ts_resume
)
...
...
drivers/input/touchscreen/mms114.c
浏览文件 @
f20c86cd
...
@@ -515,8 +515,7 @@ static int mms114_probe(struct i2c_client *client,
...
@@ -515,8 +515,7 @@ static int mms114_probe(struct i2c_client *client,
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
mms114_suspend
(
struct
device
*
dev
)
static
int
mms114_suspend
(
struct
device
*
dev
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
mms114_data
*
data
=
i2c_get_clientdata
(
client
);
struct
mms114_data
*
data
=
i2c_get_clientdata
(
client
);
...
@@ -540,7 +539,7 @@ static int mms114_suspend(struct device *dev)
...
@@ -540,7 +539,7 @@ static int mms114_suspend(struct device *dev)
return
0
;
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
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
mms114_data
*
data
=
i2c_get_clientdata
(
client
);
struct
mms114_data
*
data
=
i2c_get_clientdata
(
client
);
...
@@ -559,7 +558,6 @@ static int mms114_resume(struct device *dev)
...
@@ -559,7 +558,6 @@ static int mms114_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
mms114_pm_ops
,
mms114_suspend
,
mms114_resume
);
static
SIMPLE_DEV_PM_OPS
(
mms114_pm_ops
,
mms114_suspend
,
mms114_resume
);
...
...
drivers/input/touchscreen/pixcir_i2c_ts.c
浏览文件 @
f20c86cd
...
@@ -347,8 +347,7 @@ static void pixcir_input_close(struct input_dev *dev)
...
@@ -347,8 +347,7 @@ static void pixcir_input_close(struct input_dev *dev)
pixcir_stop
(
ts
);
pixcir_stop
(
ts
);
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
pixcir_i2c_ts_suspend
(
struct
device
*
dev
)
static
int
pixcir_i2c_ts_suspend
(
struct
device
*
dev
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
pixcir_i2c_ts_data
*
ts
=
i2c_get_clientdata
(
client
);
struct
pixcir_i2c_ts_data
*
ts
=
i2c_get_clientdata
(
client
);
...
@@ -377,7 +376,7 @@ static int pixcir_i2c_ts_suspend(struct device *dev)
...
@@ -377,7 +376,7 @@ static int pixcir_i2c_ts_suspend(struct device *dev)
return
ret
;
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
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
pixcir_i2c_ts_data
*
ts
=
i2c_get_clientdata
(
client
);
struct
pixcir_i2c_ts_data
*
ts
=
i2c_get_clientdata
(
client
);
...
@@ -405,7 +404,6 @@ static int pixcir_i2c_ts_resume(struct device *dev)
...
@@ -405,7 +404,6 @@ static int pixcir_i2c_ts_resume(struct device *dev)
return
ret
;
return
ret
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
pixcir_dev_pm_ops
,
static
SIMPLE_DEV_PM_OPS
(
pixcir_dev_pm_ops
,
pixcir_i2c_ts_suspend
,
pixcir_i2c_ts_resume
);
pixcir_i2c_ts_suspend
,
pixcir_i2c_ts_resume
);
...
...
drivers/input/touchscreen/st1232.c
浏览文件 @
f20c86cd
...
@@ -243,8 +243,7 @@ static int st1232_ts_remove(struct i2c_client *client)
...
@@ -243,8 +243,7 @@ static int st1232_ts_remove(struct i2c_client *client)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
st1232_ts_suspend
(
struct
device
*
dev
)
static
int
st1232_ts_suspend
(
struct
device
*
dev
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
st1232_ts_data
*
ts
=
i2c_get_clientdata
(
client
);
struct
st1232_ts_data
*
ts
=
i2c_get_clientdata
(
client
);
...
@@ -259,7 +258,7 @@ static int st1232_ts_suspend(struct device *dev)
...
@@ -259,7 +258,7 @@ static int st1232_ts_suspend(struct device *dev)
return
0
;
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
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
st1232_ts_data
*
ts
=
i2c_get_clientdata
(
client
);
struct
st1232_ts_data
*
ts
=
i2c_get_clientdata
(
client
);
...
@@ -274,8 +273,6 @@ static int st1232_ts_resume(struct device *dev)
...
@@ -274,8 +273,6 @@ static int st1232_ts_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
st1232_ts_pm_ops
,
static
SIMPLE_DEV_PM_OPS
(
st1232_ts_pm_ops
,
st1232_ts_suspend
,
st1232_ts_resume
);
st1232_ts_suspend
,
st1232_ts_resume
);
...
...
drivers/input/touchscreen/tsc2005.c
浏览文件 @
f20c86cd
...
@@ -773,8 +773,7 @@ static int tsc2005_remove(struct spi_device *spi)
...
@@ -773,8 +773,7 @@ static int tsc2005_remove(struct spi_device *spi)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
tsc2005_suspend
(
struct
device
*
dev
)
static
int
tsc2005_suspend
(
struct
device
*
dev
)
{
{
struct
spi_device
*
spi
=
to_spi_device
(
dev
);
struct
spi_device
*
spi
=
to_spi_device
(
dev
);
struct
tsc2005
*
ts
=
spi_get_drvdata
(
spi
);
struct
tsc2005
*
ts
=
spi_get_drvdata
(
spi
);
...
@@ -791,7 +790,7 @@ static int tsc2005_suspend(struct device *dev)
...
@@ -791,7 +790,7 @@ static int tsc2005_suspend(struct device *dev)
return
0
;
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
spi_device
*
spi
=
to_spi_device
(
dev
);
struct
tsc2005
*
ts
=
spi_get_drvdata
(
spi
);
struct
tsc2005
*
ts
=
spi_get_drvdata
(
spi
);
...
@@ -807,7 +806,6 @@ static int tsc2005_resume(struct device *dev)
...
@@ -807,7 +806,6 @@ static int tsc2005_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
tsc2005_pm_ops
,
tsc2005_suspend
,
tsc2005_resume
);
static
SIMPLE_DEV_PM_OPS
(
tsc2005_pm_ops
,
tsc2005_suspend
,
tsc2005_resume
);
...
...
drivers/input/touchscreen/ucb1400_ts.c
浏览文件 @
f20c86cd
...
@@ -406,8 +406,7 @@ static int ucb1400_ts_remove(struct platform_device *pdev)
...
@@ -406,8 +406,7 @@ static int ucb1400_ts_remove(struct platform_device *pdev)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
ucb1400_ts_suspend
(
struct
device
*
dev
)
static
int
ucb1400_ts_suspend
(
struct
device
*
dev
)
{
{
struct
ucb1400_ts
*
ucb
=
dev_get_platdata
(
dev
);
struct
ucb1400_ts
*
ucb
=
dev_get_platdata
(
dev
);
struct
input_dev
*
idev
=
ucb
->
ts_idev
;
struct
input_dev
*
idev
=
ucb
->
ts_idev
;
...
@@ -421,7 +420,7 @@ static int ucb1400_ts_suspend(struct device *dev)
...
@@ -421,7 +420,7 @@ static int ucb1400_ts_suspend(struct device *dev)
return
0
;
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
ucb1400_ts
*
ucb
=
dev_get_platdata
(
dev
);
struct
input_dev
*
idev
=
ucb
->
ts_idev
;
struct
input_dev
*
idev
=
ucb
->
ts_idev
;
...
@@ -434,7 +433,6 @@ static int ucb1400_ts_resume(struct device *dev)
...
@@ -434,7 +433,6 @@ static int ucb1400_ts_resume(struct device *dev)
mutex_unlock
(
&
idev
->
mutex
);
mutex_unlock
(
&
idev
->
mutex
);
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
ucb1400_ts_pm_ops
,
static
SIMPLE_DEV_PM_OPS
(
ucb1400_ts_pm_ops
,
ucb1400_ts_suspend
,
ucb1400_ts_resume
);
ucb1400_ts_suspend
,
ucb1400_ts_resume
);
...
...
drivers/input/touchscreen/wacom_i2c.c
浏览文件 @
f20c86cd
...
@@ -242,8 +242,7 @@ static int wacom_i2c_remove(struct i2c_client *client)
...
@@ -242,8 +242,7 @@ static int wacom_i2c_remove(struct i2c_client *client)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
wacom_i2c_suspend
(
struct
device
*
dev
)
static
int
wacom_i2c_suspend
(
struct
device
*
dev
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
...
@@ -252,7 +251,7 @@ static int wacom_i2c_suspend(struct device *dev)
...
@@ -252,7 +251,7 @@ static int wacom_i2c_suspend(struct device *dev)
return
0
;
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
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
...
@@ -260,7 +259,6 @@ static int wacom_i2c_resume(struct device *dev)
...
@@ -260,7 +259,6 @@ static int wacom_i2c_resume(struct device *dev)
return
0
;
return
0
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
wacom_i2c_pm
,
wacom_i2c_suspend
,
wacom_i2c_resume
);
static
SIMPLE_DEV_PM_OPS
(
wacom_i2c_pm
,
wacom_i2c_suspend
,
wacom_i2c_resume
);
...
...
drivers/input/touchscreen/zforce_ts.c
浏览文件 @
f20c86cd
...
@@ -602,8 +602,7 @@ static void zforce_input_close(struct input_dev *dev)
...
@@ -602,8 +602,7 @@ static void zforce_input_close(struct input_dev *dev)
return
;
return
;
}
}
#ifdef CONFIG_PM_SLEEP
static
int
__maybe_unused
zforce_suspend
(
struct
device
*
dev
)
static
int
zforce_suspend
(
struct
device
*
dev
)
{
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
zforce_ts
*
ts
=
i2c_get_clientdata
(
client
);
struct
zforce_ts
*
ts
=
i2c_get_clientdata
(
client
);
...
@@ -648,7 +647,7 @@ static int zforce_suspend(struct device *dev)
...
@@ -648,7 +647,7 @@ static int zforce_suspend(struct device *dev)
return
ret
;
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
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
zforce_ts
*
ts
=
i2c_get_clientdata
(
client
);
struct
zforce_ts
*
ts
=
i2c_get_clientdata
(
client
);
...
@@ -685,7 +684,6 @@ static int zforce_resume(struct device *dev)
...
@@ -685,7 +684,6 @@ static int zforce_resume(struct device *dev)
return
ret
;
return
ret
;
}
}
#endif
static
SIMPLE_DEV_PM_OPS
(
zforce_pm_ops
,
zforce_suspend
,
zforce_resume
);
static
SIMPLE_DEV_PM_OPS
(
zforce_pm_ops
,
zforce_suspend
,
zforce_resume
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录