Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
efe6f16c
K
Kernel
项目概览
openeuler
/
Kernel
接近 2 年 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
efe6f16c
编写于
11月 11, 2021
作者:
D
Dmitry Torokhov
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'next' into for-linus
Prepare input updates for 5.16 merge window.
上级
a02dcde5
744d0090
变更
45
隐藏空白更改
内联
并排
Showing
45 changed file
with
1833 addition
and
460 deletion
+1833
-460
Documentation/devicetree/bindings/input/cap11xx.txt
Documentation/devicetree/bindings/input/cap11xx.txt
+1
-0
Documentation/devicetree/bindings/input/cypress-sf.yaml
Documentation/devicetree/bindings/input/cypress-sf.yaml
+61
-0
MAINTAINERS
MAINTAINERS
+10
-2
drivers/input/joystick/analog.c
drivers/input/joystick/analog.c
+10
-8
drivers/input/joystick/iforce/iforce-usb.c
drivers/input/joystick/iforce/iforce-usb.c
+1
-1
drivers/input/joystick/tmdc.c
drivers/input/joystick/tmdc.c
+1
-1
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Kconfig
+10
-0
drivers/input/keyboard/Makefile
drivers/input/keyboard/Makefile
+1
-0
drivers/input/keyboard/cap11xx.c
drivers/input/keyboard/cap11xx.c
+29
-14
drivers/input/keyboard/cypress-sf.c
drivers/input/keyboard/cypress-sf.c
+224
-0
drivers/input/keyboard/ep93xx_keypad.c
drivers/input/keyboard/ep93xx_keypad.c
+64
-108
drivers/input/keyboard/mpr121_touchkey.c
drivers/input/keyboard/mpr121_touchkey.c
+2
-2
drivers/input/keyboard/omap-keypad.c
drivers/input/keyboard/omap-keypad.c
+1
-2
drivers/input/keyboard/tm2-touchkey.c
drivers/input/keyboard/tm2-touchkey.c
+7
-0
drivers/input/misc/adxl34x-i2c.c
drivers/input/misc/adxl34x-i2c.c
+3
-1
drivers/input/misc/adxl34x-spi.c
drivers/input/misc/adxl34x-spi.c
+3
-1
drivers/input/misc/adxl34x.c
drivers/input/misc/adxl34x.c
+2
-4
drivers/input/misc/adxl34x.h
drivers/input/misc/adxl34x.h
+1
-1
drivers/input/misc/ariel-pwrbutton.c
drivers/input/misc/ariel-pwrbutton.c
+7
-0
drivers/input/misc/cpcap-pwrbutton.c
drivers/input/misc/cpcap-pwrbutton.c
+5
-2
drivers/input/misc/max77693-haptic.c
drivers/input/misc/max77693-haptic.c
+0
-1
drivers/input/misc/max8925_onkey.c
drivers/input/misc/max8925_onkey.c
+1
-1
drivers/input/misc/palmas-pwrbutton.c
drivers/input/misc/palmas-pwrbutton.c
+5
-0
drivers/input/misc/pm8941-pwrkey.c
drivers/input/misc/pm8941-pwrkey.c
+5
-1
drivers/input/mouse/elantech.c
drivers/input/mouse/elantech.c
+13
-0
drivers/input/rmi4/rmi_bus.c
drivers/input/rmi4/rmi_bus.c
+1
-0
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/i8042-x86ia64io.h
+14
-0
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Kconfig
+1
-0
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/Makefile
+2
-1
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/ads7846.c
+76
-124
drivers/input/touchscreen/elants_i2c.c
drivers/input/touchscreen/elants_i2c.c
+2
-2
drivers/input/touchscreen/goodix.c
drivers/input/touchscreen/goodix.c
+106
-125
drivers/input/touchscreen/goodix.h
drivers/input/touchscreen/goodix.h
+117
-0
drivers/input/touchscreen/goodix_fwupload.c
drivers/input/touchscreen/goodix_fwupload.c
+427
-0
drivers/input/touchscreen/ili210x.c
drivers/input/touchscreen/ili210x.c
+548
-11
drivers/input/touchscreen/raydium_i2c_ts.c
drivers/input/touchscreen/raydium_i2c_ts.c
+45
-9
drivers/input/touchscreen/st1232.c
drivers/input/touchscreen/st1232.c
+2
-1
drivers/input/touchscreen/tsc2004.c
drivers/input/touchscreen/tsc2004.c
+3
-1
drivers/input/touchscreen/tsc2005.c
drivers/input/touchscreen/tsc2005.c
+3
-1
drivers/input/touchscreen/tsc200x-core.c
drivers/input/touchscreen/tsc200x-core.c
+1
-3
drivers/input/touchscreen/tsc200x-core.h
drivers/input/touchscreen/tsc200x-core.h
+1
-1
drivers/input/touchscreen/wacom_i2c.c
drivers/input/touchscreen/wacom_i2c.c
+16
-6
include/linux/input/cy8ctmg110_pdata.h
include/linux/input/cy8ctmg110_pdata.h
+0
-10
include/linux/spi/ads7846.h
include/linux/spi/ads7846.h
+0
-15
kernel/reboot.c
kernel/reboot.c
+1
-0
未找到文件。
Documentation/devicetree/bindings/input/cap11xx.txt
浏览文件 @
efe6f16c
...
...
@@ -9,6 +9,7 @@ Required properties:
"microchip,cap1106"
"microchip,cap1126"
"microchip,cap1188"
"microchip,cap1206"
reg: The I2C slave address of the device.
...
...
Documentation/devicetree/bindings/input/cypress-sf.yaml
0 → 100644
浏览文件 @
efe6f16c
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML
1.2
---
$id
:
http://devicetree.org/schemas/input/cypress-sf.yaml#
$schema
:
http://devicetree.org/meta-schemas/core.yaml#
title
:
Cypress StreetFighter touchkey controller
maintainers
:
-
Yassine Oudjana <y.oudjana@protonmail.com>
allOf
:
-
$ref
:
input.yaml#
properties
:
compatible
:
const
:
cypress,sf3155
reg
:
maxItems
:
1
interrupts
:
maxItems
:
1
avdd-supply
:
description
:
Regulator for AVDD analog voltage
vdd-supply
:
description
:
Regulator for VDD digital voltage
linux,keycodes
:
minItems
:
1
maxItems
:
8
required
:
-
compatible
-
reg
-
interrupts
-
avdd-supply
-
vdd-supply
additionalProperties
:
false
examples
:
-
|
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
touchkey@28 {
compatible = "cypress,sf3155";
reg = <0x28>;
interrupt-parent = <&msmgpio>;
interrupts = <77 IRQ_TYPE_EDGE_FALLING>;
avdd-supply = <&vreg_l6a_1p8>;
vdd-supply = <&vdd_3v2_tp>;
linux,keycodes = <KEY_BACK KEY_MENU>;
};
};
MAINTAINERS
浏览文件 @
efe6f16c
...
...
@@ -4301,7 +4301,7 @@ CHIPONE ICN8318 I2C TOUCHSCREEN DRIVER
M: Hans de Goede <hdegoede@redhat.com>
L: linux-input@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/input/touchscreen/chipone
_icn8318.txt
F: Documentation/devicetree/bindings/input/touchscreen/chipone
,icn8318.yaml
F: drivers/input/touchscreen/chipone_icn8318.c
CHIPONE ICN8505 I2C TOUCHSCREEN DRIVER
...
...
@@ -5006,6 +5006,13 @@ L: linux-input@vger.kernel.org
S: Maintained
F: drivers/input/touchscreen/cy8ctma140.c
CYPRESS STREETFIGHTER TOUCHKEYS DRIVER
M: Yassine Oudjana <y.oudjana@protonmail.com>
L: linux-input@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/input/cypress-sf.yaml
F: drivers/input/keyboard/cypress-sf.c
CYTTSP TOUCHSCREEN DRIVER
M: Linus Walleij <linus.walleij@linaro.org>
L: linux-input@vger.kernel.org
...
...
@@ -7709,9 +7716,10 @@ F: drivers/media/usb/go7007/
GOODIX TOUCHSCREEN
M: Bastien Nocera <hadess@hadess.net>
M: Hans de Goede <hdegoede@redhat.com>
L: linux-input@vger.kernel.org
S: Maintained
F: drivers/input/touchscreen/goodix
.c
F: drivers/input/touchscreen/goodix
*
GOOGLE ETHERNET DRIVERS
M: Catherine Sullivan <csully@google.com>
...
...
drivers/input/joystick/analog.c
浏览文件 @
efe6f16c
...
...
@@ -19,6 +19,7 @@
#include <linux/input.h>
#include <linux/gameport.h>
#include <linux/jiffies.h>
#include <linux/seq_buf.h>
#include <linux/timex.h>
#include <linux/timekeeping.h>
...
...
@@ -338,23 +339,24 @@ static void analog_calibrate_timer(struct analog_port *port)
static
void
analog_name
(
struct
analog
*
analog
)
{
snprintf
(
analog
->
name
,
sizeof
(
analog
->
name
),
"Analog %d-axis %d-button"
,
struct
seq_buf
s
;
seq_buf_init
(
&
s
,
analog
->
name
,
sizeof
(
analog
->
name
));
seq_buf_printf
(
&
s
,
"Analog %d-axis %d-button"
,
hweight8
(
analog
->
mask
&
ANALOG_AXES_STD
),
hweight8
(
analog
->
mask
&
ANALOG_BTNS_STD
)
+
!!
(
analog
->
mask
&
ANALOG_BTNS_CHF
)
*
2
+
hweight16
(
analog
->
mask
&
ANALOG_BTNS_GAMEPAD
)
+
!!
(
analog
->
mask
&
ANALOG_HBTN_CHF
)
*
4
);
if
(
analog
->
mask
&
ANALOG_HATS_ALL
)
s
nprintf
(
analog
->
name
,
sizeof
(
analog
->
name
),
"%s
%d-hat"
,
analog
->
name
,
hweight16
(
analog
->
mask
&
ANALOG_HATS_ALL
));
s
eq_buf_printf
(
&
s
,
"
%d-hat"
,
hweight16
(
analog
->
mask
&
ANALOG_HATS_ALL
));
if
(
analog
->
mask
&
ANALOG_HAT_FCS
)
s
trlcat
(
analog
->
name
,
" FCS"
,
sizeof
(
analog
->
name
)
);
s
eq_buf_printf
(
&
s
,
" FCS"
);
if
(
analog
->
mask
&
ANALOG_ANY_CHF
)
strlcat
(
analog
->
name
,
(
analog
->
mask
&
ANALOG_SAITEK
)
?
" Saitek"
:
" CHF"
,
sizeof
(
analog
->
name
));
seq_buf_printf
(
&
s
,
(
analog
->
mask
&
ANALOG_SAITEK
)
?
" Saitek"
:
" CHF"
);
strlcat
(
analog
->
name
,
(
analog
->
mask
&
ANALOG_GAMEPAD
)
?
" gamepad"
:
" joystick"
,
sizeof
(
analog
->
name
));
seq_buf_printf
(
&
s
,
(
analog
->
mask
&
ANALOG_GAMEPAD
)
?
" gamepad"
:
" joystick"
);
}
/*
...
...
drivers/input/joystick/iforce/iforce-usb.c
浏览文件 @
efe6f16c
...
...
@@ -92,7 +92,7 @@ static int iforce_usb_get_id(struct iforce *iforce, u8 id,
id
,
USB_TYPE_VENDOR
|
USB_DIR_IN
|
USB_RECIP_INTERFACE
,
0
,
0
,
buf
,
IFORCE_MAX_LENGTH
,
HZ
);
0
,
0
,
buf
,
IFORCE_MAX_LENGTH
,
1000
);
if
(
status
<
0
)
{
dev_err
(
&
iforce_usb
->
intf
->
dev
,
"usb_submit_urb failed: %d
\n
"
,
status
);
...
...
drivers/input/joystick/tmdc.c
浏览文件 @
efe6f16c
...
...
@@ -83,7 +83,7 @@ static const struct tmdc_model {
const
signed
char
*
axes
;
const
short
*
buttons
;
}
tmdc_models
[]
=
{
{
1
,
"ThrustMaster Millenium 3D Inceptor"
,
6
,
2
,
{
4
,
2
},
{
4
,
6
},
tmdc_abs
,
tmdc_btn_joy
},
{
1
,
"ThrustMaster Millen
n
ium 3D Inceptor"
,
6
,
2
,
{
4
,
2
},
{
4
,
6
},
tmdc_abs
,
tmdc_btn_joy
},
{
3
,
"ThrustMaster Rage 3D Gamepad"
,
2
,
0
,
{
8
,
2
},
{
0
,
0
},
tmdc_abs
,
tmdc_btn_pad
},
{
4
,
"ThrustMaster Attack Throttle"
,
5
,
2
,
{
4
,
6
},
{
4
,
2
},
tmdc_abs_at
,
tmdc_btn_at
},
{
8
,
"ThrustMaster FragMaster"
,
4
,
0
,
{
8
,
2
},
{
0
,
0
},
tmdc_abs_fm
,
tmdc_btn_fm
},
...
...
drivers/input/keyboard/Kconfig
浏览文件 @
efe6f16c
...
...
@@ -791,4 +791,14 @@ config KEYBOARD_MTK_PMIC
To compile this driver as a module, choose M here: the
module will be called pmic-keys.
config KEYBOARD_CYPRESS_SF
tristate "Cypress StreetFighter touchkey support"
depends on I2C
help
Say Y here if you want to enable support for Cypress StreetFighter
touchkeys.
To compile this driver as a module, choose M here: the
module will be called cypress-sf.
endif
drivers/input/keyboard/Makefile
浏览文件 @
efe6f16c
...
...
@@ -17,6 +17,7 @@ obj-$(CONFIG_KEYBOARD_BCM) += bcm-keypad.o
obj-$(CONFIG_KEYBOARD_CAP11XX)
+=
cap11xx.o
obj-$(CONFIG_KEYBOARD_CLPS711X)
+=
clps711x-keypad.o
obj-$(CONFIG_KEYBOARD_CROS_EC)
+=
cros_ec_keyb.o
obj-$(CONFIG_KEYBOARD_CYPRESS_SF)
+=
cypress-sf.o
obj-$(CONFIG_KEYBOARD_DAVINCI)
+=
davinci_keyscan.o
obj-$(CONFIG_KEYBOARD_DLINK_DIR685)
+=
dlink-dir685-touchkeys.o
obj-$(CONFIG_KEYBOARD_EP93XX)
+=
ep93xx_keypad.o
...
...
drivers/input/keyboard/cap11xx.c
浏览文件 @
efe6f16c
...
...
@@ -91,18 +91,21 @@ struct cap11xx_hw_model {
u8
product_id
;
unsigned
int
num_channels
;
unsigned
int
num_leds
;
bool
no_gain
;
};
enum
{
CAP1106
,
CAP1126
,
CAP1188
,
CAP1206
,
};
static
const
struct
cap11xx_hw_model
cap11xx_devices
[]
=
{
[
CAP1106
]
=
{
.
product_id
=
0x55
,
.
num_channels
=
6
,
.
num_leds
=
0
},
[
CAP1126
]
=
{
.
product_id
=
0x53
,
.
num_channels
=
6
,
.
num_leds
=
2
},
[
CAP1188
]
=
{
.
product_id
=
0x50
,
.
num_channels
=
8
,
.
num_leds
=
8
},
[
CAP1106
]
=
{
.
product_id
=
0x55
,
.
num_channels
=
6
,
.
num_leds
=
0
,
.
no_gain
=
false
},
[
CAP1126
]
=
{
.
product_id
=
0x53
,
.
num_channels
=
6
,
.
num_leds
=
2
,
.
no_gain
=
false
},
[
CAP1188
]
=
{
.
product_id
=
0x50
,
.
num_channels
=
8
,
.
num_leds
=
8
,
.
no_gain
=
false
},
[
CAP1206
]
=
{
.
product_id
=
0x67
,
.
num_channels
=
6
,
.
num_leds
=
0
,
.
no_gain
=
true
},
};
static
const
struct
reg_default
cap11xx_reg_defaults
[]
=
{
...
...
@@ -378,17 +381,24 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
node
=
dev
->
of_node
;
if
(
!
of_property_read_u32
(
node
,
"microchip,sensor-gain"
,
&
gain32
))
{
if
(
is_power_of_2
(
gain32
)
&&
gain32
<=
8
)
if
(
cap
->
no_gain
)
dev_warn
(
dev
,
"This version doesn't support sensor gain
\n
"
);
else
if
(
is_power_of_2
(
gain32
)
&&
gain32
<=
8
)
gain
=
ilog2
(
gain32
);
else
dev_err
(
dev
,
"Invalid sensor-gain value %d
\n
"
,
gain32
);
}
if
(
of_property_read_bool
(
node
,
"microchip,irq-active-high"
))
{
error
=
regmap_update_bits
(
priv
->
regmap
,
CAP11XX_REG_CONFIG2
,
CAP11XX_REG_CONFIG2_ALT_POL
,
0
);
if
(
error
)
return
error
;
if
(
id
->
driver_data
!=
CAP1206
)
{
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 */
...
...
@@ -398,11 +408,14 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
of_property_read_u32_array
(
node
,
"linux,keycodes"
,
priv
->
keycodes
,
cap
->
num_channels
);
error
=
regmap_update_bits
(
priv
->
regmap
,
CAP11XX_REG_MAIN_CONTROL
,
CAP11XX_REG_MAIN_CONTROL_GAIN_MASK
,
gain
<<
CAP11XX_REG_MAIN_CONTROL_GAIN_SHIFT
);
if
(
error
)
return
error
;
if
(
!
cap
->
no_gain
)
{
error
=
regmap_update_bits
(
priv
->
regmap
,
CAP11XX_REG_MAIN_CONTROL
,
CAP11XX_REG_MAIN_CONTROL_GAIN_MASK
,
gain
<<
CAP11XX_REG_MAIN_CONTROL_GAIN_SHIFT
);
if
(
error
)
return
error
;
}
/* Disable autorepeat. The Linux input system has its own handling. */
error
=
regmap_write
(
priv
->
regmap
,
CAP11XX_REG_REPEAT_RATE
,
0
);
...
...
@@ -470,6 +483,7 @@ static const struct of_device_id cap11xx_dt_ids[] = {
{
.
compatible
=
"microchip,cap1106"
,
},
{
.
compatible
=
"microchip,cap1126"
,
},
{
.
compatible
=
"microchip,cap1188"
,
},
{
.
compatible
=
"microchip,cap1206"
,
},
{}
};
MODULE_DEVICE_TABLE
(
of
,
cap11xx_dt_ids
);
...
...
@@ -478,6 +492,7 @@ static const struct i2c_device_id cap11xx_i2c_ids[] = {
{
"cap1106"
,
CAP1106
},
{
"cap1126"
,
CAP1126
},
{
"cap1188"
,
CAP1188
},
{
"cap1206"
,
CAP1206
},
{}
};
MODULE_DEVICE_TABLE
(
i2c
,
cap11xx_i2c_ids
);
...
...
drivers/input/keyboard/cypress-sf.c
0 → 100644
浏览文件 @
efe6f16c
// SPDX-License-Identifier: GPL-2.0-only
/*
* Cypress StreetFighter Touchkey Driver
*
* Copyright (c) 2021 Yassine Oudjana <y.oudjana@protonmail.com>
*/
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pm.h>
#include <linux/regulator/consumer.h>
#define CYPRESS_SF_DEV_NAME "cypress-sf"
#define CYPRESS_SF_REG_BUTTON_STATUS 0x4a
struct
cypress_sf_data
{
struct
i2c_client
*
client
;
struct
input_dev
*
input_dev
;
struct
regulator_bulk_data
regulators
[
2
];
u32
*
keycodes
;
unsigned
long
keystates
;
int
num_keys
;
};
static
irqreturn_t
cypress_sf_irq_handler
(
int
irq
,
void
*
devid
)
{
struct
cypress_sf_data
*
touchkey
=
devid
;
unsigned
long
keystates
,
changed
;
bool
new_state
;
int
val
,
key
;
val
=
i2c_smbus_read_byte_data
(
touchkey
->
client
,
CYPRESS_SF_REG_BUTTON_STATUS
);
if
(
val
<
0
)
{
dev_err
(
&
touchkey
->
client
->
dev
,
"Failed to read button status: %d"
,
val
);
return
IRQ_NONE
;
}
keystates
=
val
;
bitmap_xor
(
&
changed
,
&
keystates
,
&
touchkey
->
keystates
,
touchkey
->
num_keys
);
for_each_set_bit
(
key
,
&
changed
,
touchkey
->
num_keys
)
{
new_state
=
keystates
&
BIT
(
key
);
dev_dbg
(
&
touchkey
->
client
->
dev
,
"Key %d changed to %d"
,
key
,
new_state
);
input_report_key
(
touchkey
->
input_dev
,
touchkey
->
keycodes
[
key
],
new_state
);
}
input_sync
(
touchkey
->
input_dev
);
touchkey
->
keystates
=
keystates
;
return
IRQ_HANDLED
;
}
static
int
cypress_sf_probe
(
struct
i2c_client
*
client
)
{
struct
cypress_sf_data
*
touchkey
;
int
key
,
error
;
touchkey
=
devm_kzalloc
(
&
client
->
dev
,
sizeof
(
*
touchkey
),
GFP_KERNEL
);
if
(
!
touchkey
)
return
-
ENOMEM
;
touchkey
->
client
=
client
;
i2c_set_clientdata
(
client
,
touchkey
);
touchkey
->
regulators
[
0
].
supply
=
"vdd"
;
touchkey
->
regulators
[
1
].
supply
=
"avdd"
;
error
=
devm_regulator_bulk_get
(
&
client
->
dev
,
ARRAY_SIZE
(
touchkey
->
regulators
),
touchkey
->
regulators
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"Failed to get regulators: %d
\n
"
,
error
);
return
error
;
}
touchkey
->
num_keys
=
device_property_read_u32_array
(
&
client
->
dev
,
"linux,keycodes"
,
NULL
,
0
);
if
(
touchkey
->
num_keys
<
0
)
{
/* Default key count */
touchkey
->
num_keys
=
2
;
}
touchkey
->
keycodes
=
devm_kcalloc
(
&
client
->
dev
,
touchkey
->
num_keys
,
sizeof
(
*
touchkey
->
keycodes
),
GFP_KERNEL
);
if
(
!
touchkey
->
keycodes
)
return
-
ENOMEM
;
error
=
device_property_read_u32_array
(
&
client
->
dev
,
"linux,keycodes"
,
touchkey
->
keycodes
,
touchkey
->
num_keys
);
if
(
error
)
{
dev_warn
(
&
client
->
dev
,
"Failed to read keycodes: %d, using defaults
\n
"
,
error
);
/* Default keycodes */
touchkey
->
keycodes
[
0
]
=
KEY_BACK
;
touchkey
->
keycodes
[
1
]
=
KEY_MENU
;
}
error
=
regulator_bulk_enable
(
ARRAY_SIZE
(
touchkey
->
regulators
),
touchkey
->
regulators
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"Failed to enable regulators: %d
\n
"
,
error
);
return
error
;
}
touchkey
->
input_dev
=
devm_input_allocate_device
(
&
client
->
dev
);
if
(
!
touchkey
->
input_dev
)
{
dev_err
(
&
client
->
dev
,
"Failed to allocate input device
\n
"
);
return
-
ENOMEM
;
}
touchkey
->
input_dev
->
name
=
CYPRESS_SF_DEV_NAME
;
touchkey
->
input_dev
->
id
.
bustype
=
BUS_I2C
;
for
(
key
=
0
;
key
<
touchkey
->
num_keys
;
++
key
)
input_set_capability
(
touchkey
->
input_dev
,
EV_KEY
,
touchkey
->
keycodes
[
key
]);
error
=
input_register_device
(
touchkey
->
input_dev
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"Failed to register input device: %d
\n
"
,
error
);
return
error
;
}
error
=
devm_request_threaded_irq
(
&
client
->
dev
,
client
->
irq
,
NULL
,
cypress_sf_irq_handler
,
IRQF_ONESHOT
,
CYPRESS_SF_DEV_NAME
,
touchkey
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"Failed to register threaded irq: %d"
,
error
);
return
error
;
}
return
0
;
};
static
int
__maybe_unused
cypress_sf_suspend
(
struct
device
*
dev
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
cypress_sf_data
*
touchkey
=
i2c_get_clientdata
(
client
);
int
error
;
disable_irq
(
client
->
irq
);
error
=
regulator_bulk_disable
(
ARRAY_SIZE
(
touchkey
->
regulators
),
touchkey
->
regulators
);
if
(
error
)
{
dev_err
(
dev
,
"Failed to disable regulators: %d"
,
error
);
enable_irq
(
client
->
irq
);
return
error
;
}
return
0
;
}
static
int
__maybe_unused
cypress_sf_resume
(
struct
device
*
dev
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
cypress_sf_data
*
touchkey
=
i2c_get_clientdata
(
client
);
int
error
;
error
=
regulator_bulk_enable
(
ARRAY_SIZE
(
touchkey
->
regulators
),
touchkey
->
regulators
);
if
(
error
)
{
dev_err
(
dev
,
"Failed to enable regulators: %d"
,
error
);
return
error
;
}
enable_irq
(
client
->
irq
);
return
0
;
}
static
SIMPLE_DEV_PM_OPS
(
cypress_sf_pm_ops
,
cypress_sf_suspend
,
cypress_sf_resume
);
static
struct
i2c_device_id
cypress_sf_id_table
[]
=
{
{
CYPRESS_SF_DEV_NAME
,
0
},
{
}
};
MODULE_DEVICE_TABLE
(
i2c
,
cypress_sf_id_table
);
#ifdef CONFIG_OF
static
const
struct
of_device_id
cypress_sf_of_match
[]
=
{
{
.
compatible
=
"cypress,sf3155"
,
},
{
},
};
MODULE_DEVICE_TABLE
(
of
,
cypress_sf_of_match
);
#endif
static
struct
i2c_driver
cypress_sf_driver
=
{
.
driver
=
{
.
name
=
CYPRESS_SF_DEV_NAME
,
.
pm
=
&
cypress_sf_pm_ops
,
.
of_match_table
=
of_match_ptr
(
cypress_sf_of_match
),
},
.
id_table
=
cypress_sf_id_table
,
.
probe_new
=
cypress_sf_probe
,
};
module_i2c_driver
(
cypress_sf_driver
);
MODULE_AUTHOR
(
"Yassine Oudjana <y.oudjana@protonmail.com>"
);
MODULE_DESCRIPTION
(
"Cypress StreetFighter Touchkey Driver"
);
MODULE_LICENSE
(
"GPL v2"
);
drivers/input/keyboard/ep93xx_keypad.c
浏览文件 @
efe6f16c
...
...
@@ -17,6 +17,7 @@
* flag.
*/
#include <linux/bits.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
...
...
@@ -26,6 +27,7 @@
#include <linux/slab.h>
#include <linux/soc/cirrus/ep93xx.h>
#include <linux/platform_data/keypad-ep93xx.h>
#include <linux/pm_wakeirq.h>
/*
* Keypad Interface Register offsets
...
...
@@ -35,28 +37,28 @@
#define KEY_REG 0x08
/* Key Value Capture register */
/* Key Scan Initialization Register bit defines */
#define KEY_INIT_DBNC_MASK
(0x00ff0000
)
#define KEY_INIT_DBNC_SHIFT
(16)
#define KEY_INIT_DIS3KY
(1<<
15)
#define KEY_INIT_DIAG
(1<<
14)
#define KEY_INIT_BACK
(1<<
13)
#define KEY_INIT_T2
(1<<
12)
#define KEY_INIT_PRSCL_MASK
(0x000003ff
)
#define KEY_INIT_PRSCL_SHIFT
(0)
#define KEY_INIT_DBNC_MASK
GENMASK(23, 16
)
#define KEY_INIT_DBNC_SHIFT
16
#define KEY_INIT_DIS3KY
BIT(
15)
#define KEY_INIT_DIAG
BIT(
14)
#define KEY_INIT_BACK
BIT(
13)
#define KEY_INIT_T2
BIT(
12)
#define KEY_INIT_PRSCL_MASK
GENMASK(9, 0
)
#define KEY_INIT_PRSCL_SHIFT
0
/* Key Scan Diagnostic Register bit defines */
#define KEY_DIAG_MASK
(0x0000003f
)
#define KEY_DIAG_SHIFT
(0)
#define KEY_DIAG_MASK
GENMASK(5, 0
)
#define KEY_DIAG_SHIFT
0
/* Key Value Capture Register bit defines */
#define KEY_REG_K
(1<<
15)
#define KEY_REG_INT
(1<<
14)
#define KEY_REG_2KEYS
(1<<
13)
#define KEY_REG_1KEY
(1<<
12)
#define KEY_REG_KEY2_MASK
(0x00000fc0
)
#define KEY_REG_KEY2_SHIFT
(6)
#define KEY_REG_KEY1_MASK
(0x0000003f
)
#define KEY_REG_KEY1_SHIFT
(0)
#define KEY_REG_K
BIT(
15)
#define KEY_REG_INT
BIT(
14)
#define KEY_REG_2KEYS
BIT(
13)
#define KEY_REG_1KEY
BIT(
12)
#define KEY_REG_KEY2_MASK
GENMASK(11, 6
)
#define KEY_REG_KEY2_SHIFT
6
#define KEY_REG_KEY1_MASK
GENMASK(5, 0
)
#define KEY_REG_KEY1_SHIFT
0
#define EP93XX_MATRIX_SIZE (EP93XX_MATRIX_ROWS * EP93XX_MATRIX_COLS)
...
...
@@ -175,8 +177,7 @@ static void ep93xx_keypad_close(struct input_dev *pdev)
}
#ifdef CONFIG_PM_SLEEP
static
int
ep93xx_keypad_suspend
(
struct
device
*
dev
)
static
int
__maybe_unused
ep93xx_keypad_suspend
(
struct
device
*
dev
)
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
ep93xx_keypad
*
keypad
=
platform_get_drvdata
(
pdev
);
...
...
@@ -191,21 +192,15 @@ static int ep93xx_keypad_suspend(struct device *dev)
mutex_unlock
(
&
input_dev
->
mutex
);
if
(
device_may_wakeup
(
&
pdev
->
dev
))
enable_irq_wake
(
keypad
->
irq
);
return
0
;
}
static
int
ep93xx_keypad_resume
(
struct
device
*
dev
)
static
int
__maybe_unused
ep93xx_keypad_resume
(
struct
device
*
dev
)
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
ep93xx_keypad
*
keypad
=
platform_get_drvdata
(
pdev
);
struct
input_dev
*
input_dev
=
keypad
->
input_dev
;
if
(
device_may_wakeup
(
&
pdev
->
dev
))
disable_irq_wake
(
keypad
->
irq
);
mutex_lock
(
&
input_dev
->
mutex
);
if
(
input_device_enabled
(
input_dev
))
{
...
...
@@ -220,11 +215,17 @@ static int ep93xx_keypad_resume(struct device *dev)
return
0
;
}
#endif
static
SIMPLE_DEV_PM_OPS
(
ep93xx_keypad_pm_ops
,
ep93xx_keypad_suspend
,
ep93xx_keypad_resume
);
static
void
ep93xx_keypad_release_gpio_action
(
void
*
_pdev
)
{
struct
platform_device
*
pdev
=
_pdev
;
ep93xx_keypad_release_gpio
(
pdev
);
}
static
int
ep93xx_keypad_probe
(
struct
platform_device
*
pdev
)
{
struct
ep93xx_keypad
*
keypad
;
...
...
@@ -233,61 +234,46 @@ static int ep93xx_keypad_probe(struct platform_device *pdev)
struct
resource
*
res
;
int
err
;
keypad
=
kzalloc
(
sizeof
(
struct
ep93xx_
keypad
),
GFP_KERNEL
);
keypad
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
keypad
),
GFP_KERNEL
);
if
(
!
keypad
)
return
-
ENOMEM
;
keypad
->
pdata
=
dev_get_platdata
(
&
pdev
->
dev
);
if
(
!
keypad
->
pdata
)
{
err
=
-
EINVAL
;
goto
failed_free
;
}
if
(
!
keypad
->
pdata
)
return
-
EINVAL
;
keymap_data
=
keypad
->
pdata
->
keymap_data
;
if
(
!
keymap_data
)
{
err
=
-
EINVAL
;
goto
failed_free
;
}
if
(
!
keymap_data
)
return
-
EINVAL
;
keypad
->
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
keypad
->
irq
<
0
)
{
err
=
keypad
->
irq
;
goto
failed_free
;
}
if
(
keypad
->
irq
<
0
)
return
keypad
->
irq
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
res
)
{
err
=
-
ENXIO
;
goto
failed_free
;
}
if
(
!
res
)
return
-
ENXIO
;
res
=
request_mem_region
(
res
->
start
,
resource_size
(
res
),
pdev
->
name
);
if
(
!
res
)
{
err
=
-
EBUSY
;
goto
failed_free
;
}
keypad
->
mmio_base
=
ioremap
(
res
->
start
,
resource_size
(
res
));
if
(
keypad
->
mmio_base
==
NULL
)
{
err
=
-
ENXIO
;
goto
failed_free_mem
;
}
keypad
->
mmio_base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
keypad
->
mmio_base
))
return
PTR_ERR
(
keypad
->
mmio_base
);
err
=
ep93xx_keypad_acquire_gpio
(
pdev
);
if
(
err
)
goto
failed_free_io
;
return
err
;
keypad
->
clk
=
clk_get
(
&
pdev
->
dev
,
NULL
);
if
(
IS_ERR
(
keypad
->
clk
))
{
err
=
PTR_ERR
(
keypad
->
clk
);
goto
failed_free_gpio
;
}
err
=
devm_add_action_or_reset
(
&
pdev
->
dev
,
ep93xx_keypad_release_gpio_action
,
pdev
);
if
(
err
)
return
err
;
input_dev
=
input_allocate_device
();
if
(
!
input_dev
)
{
err
=
-
ENOMEM
;
goto
failed_put_clk
;
}
keypad
->
clk
=
devm_clk_get
(
&
pdev
->
dev
,
NULL
);
if
(
IS_ERR
(
keypad
->
clk
))
return
PTR_ERR
(
keypad
->
clk
);
input_dev
=
devm_input_allocate_device
(
&
pdev
->
dev
);
if
(
!
input_dev
)
return
-
ENOMEM
;
keypad
->
input_dev
=
input_dev
;
...
...
@@ -295,70 +281,40 @@ static int ep93xx_keypad_probe(struct platform_device *pdev)
input_dev
->
id
.
bustype
=
BUS_HOST
;
input_dev
->
open
=
ep93xx_keypad_open
;
input_dev
->
close
=
ep93xx_keypad_close
;
input_dev
->
dev
.
parent
=
&
pdev
->
dev
;
err
=
matrix_keypad_build_keymap
(
keymap_data
,
NULL
,
EP93XX_MATRIX_ROWS
,
EP93XX_MATRIX_COLS
,
keypad
->
keycodes
,
input_dev
);
if
(
err
)
goto
failed_free_dev
;
return
err
;
if
(
keypad
->
pdata
->
flags
&
EP93XX_KEYPAD_AUTOREPEAT
)
__set_bit
(
EV_REP
,
input_dev
->
evbit
);
input_set_drvdata
(
input_dev
,
keypad
);
err
=
request_irq
(
keypad
->
irq
,
ep93xx_keypad_irq_handler
,
0
,
pdev
->
name
,
keypad
);
err
=
devm_request_irq
(
&
pdev
->
dev
,
keypad
->
irq
,
ep93xx_keypad_irq_handler
,
0
,
pdev
->
name
,
keypad
);
if
(
err
)
goto
failed_free_dev
;
return
err
;
err
=
input_register_device
(
input_dev
);
if
(
err
)
goto
failed_free_irq
;
return
err
;
platform_set_drvdata
(
pdev
,
keypad
);
device_init_wakeup
(
&
pdev
->
dev
,
1
);
err
=
dev_pm_set_wake_irq
(
&
pdev
->
dev
,
keypad
->
irq
);
if
(
err
)
dev_warn
(
&
pdev
->
dev
,
"failed to set up wakeup irq: %d
\n
"
,
err
);
return
0
;
failed_free_irq:
free_irq
(
keypad
->
irq
,
keypad
);
failed_free_dev:
input_free_device
(
input_dev
);
failed_put_clk:
clk_put
(
keypad
->
clk
);
failed_free_gpio:
ep93xx_keypad_release_gpio
(
pdev
);
failed_free_io:
iounmap
(
keypad
->
mmio_base
);
failed_free_mem:
release_mem_region
(
res
->
start
,
resource_size
(
res
));
failed_free:
kfree
(
keypad
);
return
err
;
}
static
int
ep93xx_keypad_remove
(
struct
platform_device
*
pdev
)
{
struct
ep93xx_keypad
*
keypad
=
platform_get_drvdata
(
pdev
);
struct
resource
*
res
;
free_irq
(
keypad
->
irq
,
keypad
);
if
(
keypad
->
enabled
)
clk_disable
(
keypad
->
clk
);
clk_put
(
keypad
->
clk
);
input_unregister_device
(
keypad
->
input_dev
);
ep93xx_keypad_release_gpio
(
pdev
);
iounmap
(
keypad
->
mmio_base
);
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
release_mem_region
(
res
->
start
,
resource_size
(
res
));
kfree
(
keypad
);
dev_pm_clear_wake_irq
(
&
pdev
->
dev
);
return
0
;
}
...
...
drivers/input/keyboard/mpr121_touchkey.c
浏览文件 @
efe6f16c
...
...
@@ -107,9 +107,9 @@ static struct regulator *mpr121_vdd_supply_init(struct device *dev)
return
ERR_PTR
(
err
);
}
err
=
devm_add_action
(
dev
,
mpr121_vdd_supply_disable
,
vdd_supply
);
err
=
devm_add_action_or_reset
(
dev
,
mpr121_vdd_supply_disable
,
vdd_supply
);
if
(
err
)
{
regulator_disable
(
vdd_supply
);
dev_err
(
dev
,
"failed to add disable regulator action: %d
\n
"
,
err
);
return
ERR_PTR
(
err
);
...
...
drivers/input/keyboard/omap-keypad.c
浏览文件 @
efe6f16c
...
...
@@ -190,8 +190,7 @@ static int omap_kp_probe(struct platform_device *pdev)
row_shift
=
get_count_order
(
pdata
->
cols
);
keycodemax
=
pdata
->
rows
<<
row_shift
;
omap_kp
=
kzalloc
(
sizeof
(
struct
omap_kp
)
+
keycodemax
*
sizeof
(
unsigned
short
),
GFP_KERNEL
);
omap_kp
=
kzalloc
(
struct_size
(
omap_kp
,
keymap
,
keycodemax
),
GFP_KERNEL
);
input_dev
=
input_allocate_device
();
if
(
!
omap_kp
||
!
input_dev
)
{
kfree
(
omap_kp
);
...
...
drivers/input/keyboard/tm2-touchkey.c
浏览文件 @
efe6f16c
...
...
@@ -156,6 +156,8 @@ static irqreturn_t tm2_touchkey_irq_handler(int irq, void *devid)
goto
out
;
}
input_event
(
touchkey
->
input_dev
,
EV_MSC
,
MSC_SCAN
,
index
);
if
(
data
&
TM2_TOUCHKEY_BIT_PRESS_EV
)
{
for
(
i
=
0
;
i
<
touchkey
->
num_keycodes
;
i
++
)
input_report_key
(
touchkey
->
input_dev
,
...
...
@@ -250,6 +252,11 @@ static int tm2_touchkey_probe(struct i2c_client *client,
touchkey
->
input_dev
->
name
=
TM2_TOUCHKEY_DEV_NAME
;
touchkey
->
input_dev
->
id
.
bustype
=
BUS_I2C
;
touchkey
->
input_dev
->
keycode
=
touchkey
->
keycodes
;
touchkey
->
input_dev
->
keycodemax
=
touchkey
->
num_keycodes
;
touchkey
->
input_dev
->
keycodesize
=
sizeof
(
touchkey
->
keycodes
[
0
]);
input_set_capability
(
touchkey
->
input_dev
,
EV_MSC
,
MSC_SCAN
);
for
(
i
=
0
;
i
<
touchkey
->
num_keycodes
;
i
++
)
input_set_capability
(
touchkey
->
input_dev
,
EV_KEY
,
touchkey
->
keycodes
[
i
]);
...
...
drivers/input/misc/adxl34x-i2c.c
浏览文件 @
efe6f16c
...
...
@@ -103,7 +103,9 @@ static int adxl34x_i2c_remove(struct i2c_client *client)
{
struct
adxl34x
*
ac
=
i2c_get_clientdata
(
client
);
return
adxl34x_remove
(
ac
);
adxl34x_remove
(
ac
);
return
0
;
}
static
int
__maybe_unused
adxl34x_i2c_suspend
(
struct
device
*
dev
)
...
...
drivers/input/misc/adxl34x-spi.c
浏览文件 @
efe6f16c
...
...
@@ -91,7 +91,9 @@ static int adxl34x_spi_remove(struct spi_device *spi)
{
struct
adxl34x
*
ac
=
spi_get_drvdata
(
spi
);
return
adxl34x_remove
(
ac
);
adxl34x_remove
(
ac
);
return
0
;
}
static
int
__maybe_unused
adxl34x_spi_suspend
(
struct
device
*
dev
)
...
...
drivers/input/misc/adxl34x.c
浏览文件 @
efe6f16c
...
...
@@ -237,7 +237,7 @@ static const struct adxl34x_platform_data adxl34x_default_init = {
static
void
adxl34x_get_triple
(
struct
adxl34x
*
ac
,
struct
axis_triple
*
axis
)
{
short
buf
[
3
];
__le16
buf
[
3
];
ac
->
bops
->
read_block
(
ac
->
dev
,
DATAX0
,
DATAZ1
-
DATAX0
+
1
,
buf
);
...
...
@@ -896,15 +896,13 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
}
EXPORT_SYMBOL_GPL
(
adxl34x_probe
);
int
adxl34x_remove
(
struct
adxl34x
*
ac
)
void
adxl34x_remove
(
struct
adxl34x
*
ac
)
{
sysfs_remove_group
(
&
ac
->
dev
->
kobj
,
&
adxl34x_attr_group
);
free_irq
(
ac
->
irq
,
ac
);
input_unregister_device
(
ac
->
input
);
dev_dbg
(
ac
->
dev
,
"unregistered accelerometer
\n
"
);
kfree
(
ac
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
adxl34x_remove
);
...
...
drivers/input/misc/adxl34x.h
浏览文件 @
efe6f16c
...
...
@@ -25,6 +25,6 @@ void adxl34x_resume(struct adxl34x *ac);
struct
adxl34x
*
adxl34x_probe
(
struct
device
*
dev
,
int
irq
,
bool
fifo_delay_default
,
const
struct
adxl34x_bus_ops
*
bops
);
int
adxl34x_remove
(
struct
adxl34x
*
ac
);
void
adxl34x_remove
(
struct
adxl34x
*
ac
);
#endif
drivers/input/misc/ariel-pwrbutton.c
浏览文件 @
efe6f16c
...
...
@@ -149,12 +149,19 @@ static const struct of_device_id ariel_pwrbutton_of_match[] = {
};
MODULE_DEVICE_TABLE
(
of
,
ariel_pwrbutton_of_match
);
static
const
struct
spi_device_id
ariel_pwrbutton_spi_ids
[]
=
{
{
.
name
=
"wyse-ariel-ec-input"
},
{
}
};
MODULE_DEVICE_TABLE
(
spi
,
ariel_pwrbutton_spi_ids
);
static
struct
spi_driver
ariel_pwrbutton_driver
=
{
.
driver
=
{
.
name
=
"dell-wyse-ariel-ec-input"
,
.
of_match_table
=
ariel_pwrbutton_of_match
,
},
.
probe
=
ariel_pwrbutton_probe
,
.
id_table
=
ariel_pwrbutton_spi_ids
,
};
module_spi_driver
(
ariel_pwrbutton_driver
);
...
...
drivers/input/misc/cpcap-pwrbutton.c
浏览文件 @
efe6f16c
...
...
@@ -54,9 +54,13 @@ static irqreturn_t powerbutton_irq(int irq, void *_button)
static
int
cpcap_power_button_probe
(
struct
platform_device
*
pdev
)
{
struct
cpcap_power_button
*
button
;
int
irq
=
platform_get_irq
(
pdev
,
0
)
;
int
irq
;
int
err
;
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
irq
<
0
)
return
irq
;
button
=
devm_kmalloc
(
&
pdev
->
dev
,
sizeof
(
*
button
),
GFP_KERNEL
);
if
(
!
button
)
return
-
ENOMEM
;
...
...
@@ -73,7 +77,6 @@ static int cpcap_power_button_probe(struct platform_device *pdev)
button
->
idev
->
name
=
"cpcap-pwrbutton"
;
button
->
idev
->
phys
=
"cpcap-pwrbutton/input0"
;
button
->
idev
->
dev
.
parent
=
button
->
dev
;
input_set_capability
(
button
->
idev
,
EV_KEY
,
KEY_POWER
);
err
=
devm_request_threaded_irq
(
&
pdev
->
dev
,
irq
,
NULL
,
...
...
drivers/input/misc/max77693-haptic.c
浏览文件 @
efe6f16c
...
...
@@ -424,5 +424,4 @@ module_platform_driver(max77693_haptic_driver);
MODULE_AUTHOR
(
"Jaewon Kim <jaewon02.kim@samsung.com>"
);
MODULE_AUTHOR
(
"Krzysztof Kozlowski <krzk@kernel.org>"
);
MODULE_DESCRIPTION
(
"MAXIM 77693/77843 Haptic driver"
);
MODULE_ALIAS
(
"platform:max77693-haptic"
);
MODULE_LICENSE
(
"GPL"
);
drivers/input/misc/max8925_onkey.c
浏览文件 @
efe6f16c
/*
*
/*
* MAX8925 ONKEY driver
*
* Copyright (C) 2009 Marvell International Ltd.
...
...
drivers/input/misc/palmas-pwrbutton.c
浏览文件 @
efe6f16c
...
...
@@ -210,6 +210,11 @@ static int palmas_pwron_probe(struct platform_device *pdev)
INIT_DELAYED_WORK
(
&
pwron
->
input_work
,
palmas_power_button_work
);
pwron
->
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
pwron
->
irq
<
0
)
{
error
=
pwron
->
irq
;
goto
err_free_input
;
}
error
=
request_threaded_irq
(
pwron
->
irq
,
NULL
,
pwron_irq
,
IRQF_TRIGGER_HIGH
|
IRQF_TRIGGER_LOW
|
...
...
drivers/input/misc/pm8941-pwrkey.c
浏览文件 @
efe6f16c
...
...
@@ -29,6 +29,7 @@
#define PON_PS_HOLD_RST_CTL2 0x5b
#define PON_PS_HOLD_ENABLE BIT(7)
#define PON_PS_HOLD_TYPE_MASK 0x0f
#define PON_PS_HOLD_TYPE_WARM_RESET 1
#define PON_PS_HOLD_TYPE_SHUTDOWN 4
#define PON_PS_HOLD_TYPE_HARD_RESET 7
...
...
@@ -99,7 +100,10 @@ static int pm8941_reboot_notify(struct notifier_block *nb,
break
;
case
SYS_RESTART
:
default:
reset_type
=
PON_PS_HOLD_TYPE_HARD_RESET
;
if
(
reboot_mode
==
REBOOT_WARM
)
reset_type
=
PON_PS_HOLD_TYPE_WARM_RESET
;
else
reset_type
=
PON_PS_HOLD_TYPE_HARD_RESET
;
break
;
}
...
...
drivers/input/mouse/elantech.c
浏览文件 @
efe6f16c
...
...
@@ -517,6 +517,19 @@ static void elantech_report_trackpoint(struct psmouse *psmouse,
case
0x16008020U
:
case
0x26800010U
:
case
0x36808000U
:
/*
* This firmware misreport coordinates for trackpoint
* occasionally. Discard packets outside of [-127, 127] range
* to prevent cursor jumps.
*/
if
(
packet
[
4
]
==
0x80
||
packet
[
5
]
==
0x80
||
packet
[
1
]
>>
7
==
packet
[
4
]
>>
7
||
packet
[
2
]
>>
7
==
packet
[
5
]
>>
7
)
{
elantech_debug
(
"discarding packet [%6ph]
\n
"
,
packet
);
break
;
}
x
=
packet
[
4
]
-
(
int
)((
packet
[
1
]
^
0x80
)
<<
1
);
y
=
(
int
)((
packet
[
2
]
^
0x80
)
<<
1
)
-
packet
[
5
];
...
...
drivers/input/rmi4/rmi_bus.c
浏览文件 @
efe6f16c
...
...
@@ -90,6 +90,7 @@ int rmi_register_transport_device(struct rmi_transport_dev *xport)
rmi_dev
->
dev
.
bus
=
&
rmi_bus_type
;
rmi_dev
->
dev
.
type
=
&
rmi_device_type
;
rmi_dev
->
dev
.
parent
=
xport
->
dev
;
xport
->
rmi_dev
=
rmi_dev
;
...
...
drivers/input/serio/i8042-x86ia64io.h
浏览文件 @
efe6f16c
...
...
@@ -272,6 +272,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"LifeBook S6230"
),
},
},
{
/* Fujitsu Lifebook T725 laptop */
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"FUJITSU"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"LIFEBOOK T725"
),
},
},
{
/* Fujitsu Lifebook U745 */
.
matches
=
{
...
...
@@ -840,6 +847,13 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = {
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"LIFEBOOK AH544"
),
},
},
{
/* Fujitsu Lifebook T725 laptop */
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"FUJITSU"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"LIFEBOOK T725"
),
},
},
{
/* Fujitsu U574 laptop */
/* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
...
...
drivers/input/touchscreen/Kconfig
浏览文件 @
efe6f16c
...
...
@@ -425,6 +425,7 @@ config TOUCHSCREEN_HYCON_HY46XX
config TOUCHSCREEN_ILI210X
tristate "Ilitek ILI210X based touchscreen"
depends on I2C
select CRC_CCITT
help
Say Y here if you have a ILI210X based touchscreen
controller. This driver supports models ILI2102,
...
...
drivers/input/touchscreen/Makefile
浏览文件 @
efe6f16c
...
...
@@ -6,6 +6,7 @@
# Each configuration option enables a list of files.
wm97xx-ts-y
:=
wm97xx-core.o
goodix_ts-y
:=
goodix.o goodix_fwupload.o
obj-$(CONFIG_TOUCHSCREEN_88PM860X)
+=
88pm860x-ts.o
obj-$(CONFIG_TOUCHSCREEN_AD7877)
+=
ad7877.o
...
...
@@ -44,7 +45,7 @@ obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL)
+=
egalax_ts_serial.o
obj-$(CONFIG_TOUCHSCREEN_EXC3000)
+=
exc3000.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU)
+=
fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX)
+=
goodix.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX)
+=
goodix
_ts
.o
obj-$(CONFIG_TOUCHSCREEN_HIDEEP)
+=
hideep.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X)
+=
ili210x.o
obj-$(CONFIG_TOUCHSCREEN_ILITEK)
+=
ilitek_ts_i2c.o
...
...
drivers/input/touchscreen/ads7846.c
浏览文件 @
efe6f16c
...
...
@@ -101,10 +101,6 @@ struct ads7846 {
struct
spi_device
*
spi
;
struct
regulator
*
reg
;
#if IS_ENABLED(CONFIG_HWMON)
struct
device
*
hwmon
;
#endif
u16
model
;
u16
vref_mv
;
u16
vref_delay_usecs
;
...
...
@@ -142,13 +138,18 @@ struct ads7846 {
int
(
*
filter
)(
void
*
data
,
int
data_idx
,
int
*
val
);
void
*
filter_data
;
void
(
*
filter_cleanup
)(
void
*
data
);
int
(
*
get_pendown_state
)(
void
);
int
gpio_pendown
;
void
(
*
wait_for_sync
)(
void
);
};
enum
ads7846_filter
{
ADS7846_FILTER_OK
,
ADS7846_FILTER_REPEAT
,
ADS7846_FILTER_IGNORE
,
};
/* leave chip selected when we're done, for quicker re-select? */
#if 0
#define CS_CHANGE(xfer) ((xfer).cs_change = 1)
...
...
@@ -549,6 +550,8 @@ __ATTRIBUTE_GROUPS(ads7846_attr);
static
int
ads784x_hwmon_register
(
struct
spi_device
*
spi
,
struct
ads7846
*
ts
)
{
struct
device
*
hwmon
;
/* hwmon sensors need a reference voltage */
switch
(
ts
->
model
)
{
case
7846
:
...
...
@@ -569,17 +572,11 @@ static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts)
break
;
}
ts
->
hwmon
=
hwmon_device_register_with_groups
(
&
spi
->
dev
,
spi
->
modalias
,
ts
,
ads7846_attr_groups
);
hwmon
=
devm_hwmon_device_register_with_groups
(
&
spi
->
dev
,
spi
->
modalias
,
ts
,
ads7846_attr_groups
);
return
PTR_ERR_OR_ZERO
(
ts
->
hwmon
);
}
static
void
ads784x_hwmon_unregister
(
struct
spi_device
*
spi
,
struct
ads7846
*
ts
)
{
if
(
ts
->
hwmon
)
hwmon_device_unregister
(
ts
->
hwmon
);
return
PTR_ERR_OR_ZERO
(
hwmon
);
}
#else
...
...
@@ -588,11 +585,6 @@ static inline int ads784x_hwmon_register(struct spi_device *spi,
{
return
0
;
}
static
inline
void
ads784x_hwmon_unregister
(
struct
spi_device
*
spi
,
struct
ads7846
*
ts
)
{
}
#endif
static
ssize_t
ads7846_pen_down_show
(
struct
device
*
dev
,
...
...
@@ -1014,8 +1006,8 @@ static int ads7846_setup_pendown(struct spi_device *spi,
ts
->
get_pendown_state
=
pdata
->
get_pendown_state
;
}
else
if
(
gpio_is_valid
(
pdata
->
gpio_pendown
))
{
err
=
gpio_request_one
(
pdata
->
gpio_pendown
,
GPIOF_IN
,
"ads7846_pendown"
);
err
=
devm_gpio_request_one
(
&
spi
->
dev
,
pdata
->
gpio_pendown
,
GPIOF_IN
,
"ads7846_pendown"
);
if
(
err
)
{
dev_err
(
&
spi
->
dev
,
"failed to request/setup pendown GPIO%d: %d
\n
"
,
...
...
@@ -1212,24 +1204,30 @@ static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev)
}
#endif
static
void
ads7846_regulator_disable
(
void
*
regulator
)
{
regulator_disable
(
regulator
);
}
static
int
ads7846_probe
(
struct
spi_device
*
spi
)
{
const
struct
ads7846_platform_data
*
pdata
;
struct
ads7846
*
ts
;
struct
device
*
dev
=
&
spi
->
dev
;
struct
ads7846_packet
*
packet
;
struct
input_dev
*
input_dev
;
unsigned
long
irq_flags
;
int
err
;
if
(
!
spi
->
irq
)
{
dev_dbg
(
&
spi
->
dev
,
"no IRQ?
\n
"
);
dev_dbg
(
dev
,
"no IRQ?
\n
"
);
return
-
EINVAL
;
}
/* don't exceed max specified sample rate */
if
(
spi
->
max_speed_hz
>
(
125000
*
SAMPLE_BITS
))
{
dev_err
(
&
spi
->
dev
,
"f(sample) %d KHz?
\n
"
,
(
spi
->
max_speed_hz
/
SAMPLE_BITS
)
/
1000
);
dev_err
(
dev
,
"f(sample) %d KHz?
\n
"
,
(
spi
->
max_speed_hz
/
SAMPLE_BITS
)
/
1000
);
return
-
EINVAL
;
}
...
...
@@ -1245,13 +1243,17 @@ static int ads7846_probe(struct spi_device *spi)
if
(
err
<
0
)
return
err
;
ts
=
kzalloc
(
sizeof
(
struct
ads7846
),
GFP_KERNEL
);
packet
=
kzalloc
(
sizeof
(
struct
ads7846_packet
),
GFP_KERNEL
);
input_dev
=
input_allocate_device
();
if
(
!
ts
||
!
packet
||
!
input_dev
)
{
err
=
-
ENOMEM
;
goto
err_free_mem
;
}
ts
=
devm_kzalloc
(
dev
,
sizeof
(
struct
ads7846
),
GFP_KERNEL
);
if
(
!
ts
)
return
-
ENOMEM
;
packet
=
devm_kzalloc
(
dev
,
sizeof
(
struct
ads7846_packet
),
GFP_KERNEL
);
if
(
!
packet
)
return
-
ENOMEM
;
input_dev
=
devm_input_allocate_device
(
dev
);
if
(
!
input_dev
)
return
-
ENOMEM
;
spi_set_drvdata
(
spi
,
ts
);
...
...
@@ -1262,13 +1264,11 @@ static int ads7846_probe(struct spi_device *spi)
mutex_init
(
&
ts
->
lock
);
init_waitqueue_head
(
&
ts
->
wait
);
pdata
=
dev_get_platdata
(
&
spi
->
dev
);
pdata
=
dev_get_platdata
(
dev
);
if
(
!
pdata
)
{
pdata
=
ads7846_probe_dt
(
&
spi
->
dev
);
if
(
IS_ERR
(
pdata
))
{
err
=
PTR_ERR
(
pdata
);
goto
err_free_mem
;
}
pdata
=
ads7846_probe_dt
(
dev
);
if
(
IS_ERR
(
pdata
))
return
PTR_ERR
(
pdata
);
}
ts
->
model
=
pdata
->
model
?
:
7846
;
...
...
@@ -1276,15 +1276,7 @@ static int ads7846_probe(struct spi_device *spi)
ts
->
x_plate_ohms
=
pdata
->
x_plate_ohms
?
:
400
;
ts
->
vref_mv
=
pdata
->
vref_mv
;
if
(
pdata
->
filter
!=
NULL
)
{
if
(
pdata
->
filter_init
!=
NULL
)
{
err
=
pdata
->
filter_init
(
pdata
,
&
ts
->
filter_data
);
if
(
err
<
0
)
goto
err_free_mem
;
}
ts
->
filter
=
pdata
->
filter
;
ts
->
filter_cleanup
=
pdata
->
filter_cleanup
;
}
else
if
(
pdata
->
debounce_max
)
{
if
(
pdata
->
debounce_max
)
{
ts
->
debounce_max
=
pdata
->
debounce_max
;
if
(
ts
->
debounce_max
<
2
)
ts
->
debounce_max
=
2
;
...
...
@@ -1298,7 +1290,7 @@ static int ads7846_probe(struct spi_device *spi)
err
=
ads7846_setup_pendown
(
spi
,
ts
,
pdata
);
if
(
err
)
goto
err_cleanup_filte
r
;
return
er
r
;
if
(
pdata
->
penirq_recheck_delay_usecs
)
ts
->
penirq_recheck_delay_usecs
=
...
...
@@ -1306,15 +1298,16 @@ static int ads7846_probe(struct spi_device *spi)
ts
->
wait_for_sync
=
pdata
->
wait_for_sync
?
:
null_wait_for_sync
;
snprintf
(
ts
->
phys
,
sizeof
(
ts
->
phys
),
"%s/input0"
,
dev_name
(
&
spi
->
dev
));
snprintf
(
ts
->
phys
,
sizeof
(
ts
->
phys
),
"%s/input0"
,
dev_name
(
dev
));
snprintf
(
ts
->
name
,
sizeof
(
ts
->
name
),
"ADS%d Touchscreen"
,
ts
->
model
);
input_dev
->
name
=
ts
->
name
;
input_dev
->
phys
=
ts
->
phys
;
input_dev
->
dev
.
parent
=
&
spi
->
dev
;
input_dev
->
evbit
[
0
]
=
BIT_MASK
(
EV_KEY
)
|
BIT_MASK
(
EV_ABS
);
input_dev
->
keybit
[
BIT_WORD
(
BTN_TOUCH
)]
=
BIT_MASK
(
BTN_TOUCH
);
input_dev
->
id
.
bustype
=
BUS_SPI
;
input_dev
->
id
.
product
=
pdata
->
model
;
input_set_capability
(
input_dev
,
EV_KEY
,
BTN_TOUCH
);
input_set_abs_params
(
input_dev
,
ABS_X
,
pdata
->
x_min
?
:
0
,
pdata
->
x_max
?
:
MAX_12BIT
,
...
...
@@ -1345,125 +1338,84 @@ static int ads7846_probe(struct spi_device *spi)
ads7846_setup_spi_msg
(
ts
,
pdata
);
ts
->
reg
=
regulator_get
(
&
spi
->
dev
,
"vcc"
);
ts
->
reg
=
devm_regulator_get
(
dev
,
"vcc"
);
if
(
IS_ERR
(
ts
->
reg
))
{
err
=
PTR_ERR
(
ts
->
reg
);
dev_err
(
&
spi
->
dev
,
"unable to get regulator: %d
\n
"
,
err
);
goto
err_free_gpio
;
dev_err
(
dev
,
"unable to get regulator: %d
\n
"
,
err
);
return
err
;
}
err
=
regulator_enable
(
ts
->
reg
);
if
(
err
)
{
dev_err
(
&
spi
->
dev
,
"unable to enable regulator: %d
\n
"
,
err
);
goto
err_put_regulato
r
;
dev_err
(
dev
,
"unable to enable regulator: %d
\n
"
,
err
);
return
er
r
;
}
err
=
devm_add_action_or_reset
(
dev
,
ads7846_regulator_disable
,
ts
->
reg
);
if
(
err
)
return
err
;
irq_flags
=
pdata
->
irq_flags
?
:
IRQF_TRIGGER_FALLING
;
irq_flags
|=
IRQF_ONESHOT
;
err
=
request_threaded_irq
(
spi
->
irq
,
ads7846_hard_irq
,
ads7846_irq
,
irq_flags
,
spi
->
dev
.
driver
->
name
,
ts
);
if
(
err
&&
!
pdata
->
irq_flags
)
{
dev_info
(
&
spi
->
dev
,
err
=
devm_request_threaded_irq
(
dev
,
spi
->
irq
,
ads7846_hard_irq
,
ads7846_irq
,
irq_flags
,
dev
->
driver
->
name
,
ts
);
if
(
err
&&
err
!=
-
EPROBE_DEFER
&&
!
pdata
->
irq_flags
)
{
dev_info
(
dev
,
"trying pin change workaround on irq %d
\n
"
,
spi
->
irq
);
irq_flags
|=
IRQF_TRIGGER_RISING
;
err
=
request_threaded_irq
(
spi
->
irq
,
ads7846_hard_irq
,
ads7846_irq
,
irq_flags
,
spi
->
dev
.
driver
->
name
,
ts
);
err
=
devm_request_threaded_irq
(
dev
,
spi
->
irq
,
ads7846_hard_irq
,
ads7846_irq
,
irq_flags
,
dev
->
driver
->
name
,
ts
);
}
if
(
err
)
{
dev_dbg
(
&
spi
->
dev
,
"irq %d busy?
\n
"
,
spi
->
irq
);
goto
err_disable_regulato
r
;
dev_dbg
(
dev
,
"irq %d busy?
\n
"
,
spi
->
irq
);
return
er
r
;
}
err
=
ads784x_hwmon_register
(
spi
,
ts
);
if
(
err
)
goto
err_free_irq
;
return
err
;
dev_info
(
&
spi
->
dev
,
"touchscreen, irq %d
\n
"
,
spi
->
irq
);
dev_info
(
dev
,
"touchscreen, irq %d
\n
"
,
spi
->
irq
);
/*
* Take a first sample, leaving nPENIRQ active and vREF off; avoid
* the touchscreen, in case it's not connected.
*/
if
(
ts
->
model
==
7845
)
ads7845_read12_ser
(
&
spi
->
dev
,
PWRDOWN
);
ads7845_read12_ser
(
dev
,
PWRDOWN
);
else
(
void
)
ads7846_read12_ser
(
&
spi
->
dev
,
READ_12BIT_SER
(
vaux
));
(
void
)
ads7846_read12_ser
(
dev
,
READ_12BIT_SER
(
vaux
));
err
=
sysfs_create_group
(
&
spi
->
dev
.
kobj
,
&
ads784x_attr_group
);
err
=
devm_device_add_group
(
dev
,
&
ads784x_attr_group
);
if
(
err
)
goto
err_remove_hwmon
;
return
err
;
err
=
input_register_device
(
input_dev
);
if
(
err
)
goto
err_remove_attr_group
;
return
err
;
device_init_wakeup
(
&
spi
->
dev
,
pdata
->
wakeup
);
device_init_wakeup
(
dev
,
pdata
->
wakeup
);
/*
* If device does not carry platform data we must have allocated it
* when parsing DT data.
*/
if
(
!
dev_get_platdata
(
&
spi
->
dev
))
devm_kfree
(
&
spi
->
dev
,
(
void
*
)
pdata
);
if
(
!
dev_get_platdata
(
dev
))
devm_kfree
(
dev
,
(
void
*
)
pdata
);
return
0
;
err_remove_attr_group:
sysfs_remove_group
(
&
spi
->
dev
.
kobj
,
&
ads784x_attr_group
);
err_remove_hwmon:
ads784x_hwmon_unregister
(
spi
,
ts
);
err_free_irq:
free_irq
(
spi
->
irq
,
ts
);
err_disable_regulator:
regulator_disable
(
ts
->
reg
);
err_put_regulator:
regulator_put
(
ts
->
reg
);
err_free_gpio:
if
(
!
ts
->
get_pendown_state
)
gpio_free
(
ts
->
gpio_pendown
);
err_cleanup_filter:
if
(
ts
->
filter_cleanup
)
ts
->
filter_cleanup
(
ts
->
filter_data
);
err_free_mem:
input_free_device
(
input_dev
);
kfree
(
packet
);
kfree
(
ts
);
return
err
;
}
static
int
ads7846_remove
(
struct
spi_device
*
spi
)
{
struct
ads7846
*
ts
=
spi_get_drvdata
(
spi
);
sysfs_remove_group
(
&
spi
->
dev
.
kobj
,
&
ads784x_attr_group
);
ads7846_disable
(
ts
);
free_irq
(
ts
->
spi
->
irq
,
ts
);
input_unregister_device
(
ts
->
input
);
ads784x_hwmon_unregister
(
spi
,
ts
);
regulator_put
(
ts
->
reg
);
if
(
!
ts
->
get_pendown_state
)
{
/*
* If we are not using specialized pendown method we must
* have been relying on gpio we set up ourselves.
*/
gpio_free
(
ts
->
gpio_pendown
);
}
if
(
ts
->
filter_cleanup
)
ts
->
filter_cleanup
(
ts
->
filter_data
);
kfree
(
ts
->
packet
);
kfree
(
ts
);
dev_dbg
(
&
spi
->
dev
,
"unregistered touchscreen
\n
"
);
ads7846_stop
(
ts
);
return
0
;
}
...
...
drivers/input/touchscreen/elants_i2c.c
浏览文件 @
efe6f16c
...
...
@@ -1439,11 +1439,11 @@ static int elants_i2c_probe(struct i2c_client *client)
if
(
error
)
return
error
;
error
=
devm_add_action
(
&
client
->
dev
,
elants_i2c_power_off
,
ts
);
error
=
devm_add_action_or_reset
(
&
client
->
dev
,
elants_i2c_power_off
,
ts
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"failed to install power off action: %d
\n
"
,
error
);
elants_i2c_power_off
(
ts
);
return
error
;
}
...
...
drivers/input/touchscreen/goodix.c
浏览文件 @
efe6f16c
...
...
@@ -14,20 +14,15 @@
#include <linux/kernel.h>
#include <linux/dmi.h>
#include <linux/firmware.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/of.h>
#include <asm/unaligned.h>
#include "goodix.h"
#define GOODIX_GPIO_INT_NAME "irq"
#define GOODIX_GPIO_RST_NAME "reset"
...
...
@@ -38,22 +33,11 @@
#define GOODIX_CONTACT_SIZE 8
#define GOODIX_MAX_CONTACT_SIZE 9
#define GOODIX_MAX_CONTACTS 10
#define GOODIX_MAX_KEYS 7
#define GOODIX_CONFIG_MIN_LENGTH 186
#define GOODIX_CONFIG_911_LENGTH 186
#define GOODIX_CONFIG_967_LENGTH 228
#define GOODIX_CONFIG_GT9X_LENGTH 240
#define GOODIX_CONFIG_MAX_LENGTH 240
/* Register defines */
#define GOODIX_REG_COMMAND 0x8040
#define GOODIX_CMD_SCREEN_OFF 0x05
#define GOODIX_READ_COOR_ADDR 0x814E
#define GOODIX_GT1X_REG_CONFIG_DATA 0x8050
#define GOODIX_GT9X_REG_CONFIG_DATA 0x8047
#define GOODIX_REG_ID 0x8140
#define GOODIX_BUFFER_STATUS_READY BIT(7)
#define GOODIX_HAVE_KEY BIT(4)
...
...
@@ -68,55 +52,11 @@
#define ACPI_GPIO_SUPPORT
#endif
struct
goodix_ts_data
;
enum
goodix_irq_pin_access_method
{
IRQ_PIN_ACCESS_NONE
,
IRQ_PIN_ACCESS_GPIO
,
IRQ_PIN_ACCESS_ACPI_GPIO
,
IRQ_PIN_ACCESS_ACPI_METHOD
,
};
struct
goodix_chip_data
{
u16
config_addr
;
int
config_len
;
int
(
*
check_config
)(
struct
goodix_ts_data
*
ts
,
const
u8
*
cfg
,
int
len
);
void
(
*
calc_config_checksum
)(
struct
goodix_ts_data
*
ts
);
};
struct
goodix_chip_id
{
const
char
*
id
;
const
struct
goodix_chip_data
*
data
;
};
#define GOODIX_ID_MAX_LEN 4
struct
goodix_ts_data
{
struct
i2c_client
*
client
;
struct
input_dev
*
input_dev
;
const
struct
goodix_chip_data
*
chip
;
struct
touchscreen_properties
prop
;
unsigned
int
max_touch_num
;
unsigned
int
int_trigger_type
;
struct
regulator
*
avdd28
;
struct
regulator
*
vddio
;
struct
gpio_desc
*
gpiod_int
;
struct
gpio_desc
*
gpiod_rst
;
int
gpio_count
;
int
gpio_int_idx
;
char
id
[
GOODIX_ID_MAX_LEN
+
1
];
u16
version
;
const
char
*
cfg_name
;
bool
reset_controller_at_probe
;
bool
load_cfg_from_disk
;
struct
completion
firmware_loading_complete
;
unsigned
long
irq_flags
;
enum
goodix_irq_pin_access_method
irq_pin_access_method
;
unsigned
int
contact_size
;
u8
config
[
GOODIX_CONFIG_MAX_LENGTH
];
unsigned
short
keymap
[
GOODIX_MAX_KEYS
];
};
static
int
goodix_check_cfg_8
(
struct
goodix_ts_data
*
ts
,
const
u8
*
cfg
,
int
len
);
static
int
goodix_check_cfg_16
(
struct
goodix_ts_data
*
ts
,
...
...
@@ -260,8 +200,7 @@ static const struct dmi_system_id inverted_x_screen[] = {
* @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
)
int
goodix_i2c_read
(
struct
i2c_client
*
client
,
u16
reg
,
u8
*
buf
,
int
len
)
{
struct
i2c_msg
msgs
[
2
];
__be16
wbuf
=
cpu_to_be16
(
reg
);
...
...
@@ -278,7 +217,13 @@ static int goodix_i2c_read(struct i2c_client *client,
msgs
[
1
].
buf
=
buf
;
ret
=
i2c_transfer
(
client
->
adapter
,
msgs
,
2
);
return
ret
<
0
?
ret
:
(
ret
!=
ARRAY_SIZE
(
msgs
)
?
-
EIO
:
0
);
if
(
ret
>=
0
)
ret
=
(
ret
==
ARRAY_SIZE
(
msgs
)
?
0
:
-
EIO
);
if
(
ret
)
dev_err
(
&
client
->
dev
,
"Error reading %d bytes from 0x%04x: %d
\n
"
,
len
,
reg
,
ret
);
return
ret
;
}
/**
...
...
@@ -289,8 +234,7 @@ static int goodix_i2c_read(struct i2c_client *client,
* @buf: raw data buffer to write.
* @len: length of the buffer to write
*/
static
int
goodix_i2c_write
(
struct
i2c_client
*
client
,
u16
reg
,
const
u8
*
buf
,
unsigned
len
)
int
goodix_i2c_write
(
struct
i2c_client
*
client
,
u16
reg
,
const
u8
*
buf
,
int
len
)
{
u8
*
addr_buf
;
struct
i2c_msg
msg
;
...
...
@@ -310,11 +254,18 @@ static int goodix_i2c_write(struct i2c_client *client, u16 reg, const u8 *buf,
msg
.
len
=
len
+
2
;
ret
=
i2c_transfer
(
client
->
adapter
,
&
msg
,
1
);
if
(
ret
>=
0
)
ret
=
(
ret
==
1
?
0
:
-
EIO
);
kfree
(
addr_buf
);
return
ret
<
0
?
ret
:
(
ret
!=
1
?
-
EIO
:
0
);
if
(
ret
)
dev_err
(
&
client
->
dev
,
"Error writing %d bytes to 0x%04x: %d
\n
"
,
len
,
reg
,
ret
);
return
ret
;
}
static
int
goodix_i2c_write_u8
(
struct
i2c_client
*
client
,
u16
reg
,
u8
value
)
int
goodix_i2c_write_u8
(
struct
i2c_client
*
client
,
u16
reg
,
u8
value
)
{
return
goodix_i2c_write
(
client
,
reg
,
&
value
,
sizeof
(
value
));
}
...
...
@@ -353,11 +304,8 @@ static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data)
do
{
error
=
goodix_i2c_read
(
ts
->
client
,
addr
,
data
,
header_contact_keycode_size
);
if
(
error
)
{
dev_err
(
&
ts
->
client
->
dev
,
"I2C transfer error: %d
\n
"
,
error
);
if
(
error
)
return
error
;
}
if
(
data
[
0
]
&
GOODIX_BUFFER_STATUS_READY
)
{
touch_num
=
data
[
0
]
&
0x0f
;
...
...
@@ -378,6 +326,11 @@ static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data)
return
touch_num
;
}
if
(
data
[
0
]
==
0
&&
ts
->
firmware_name
)
{
if
(
goodix_handle_fw_request
(
ts
))
return
0
;
}
usleep_range
(
1000
,
2000
);
/* Poll every 1 - 2 ms */
}
while
(
time_before
(
jiffies
,
max_timeout
));
...
...
@@ -480,9 +433,7 @@ static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
struct
goodix_ts_data
*
ts
=
dev_id
;
goodix_process_events
(
ts
);
if
(
goodix_i2c_write_u8
(
ts
->
client
,
GOODIX_READ_COOR_ADDR
,
0
)
<
0
)
dev_err
(
&
ts
->
client
->
dev
,
"I2C write end_cmd error
\n
"
);
goodix_i2c_write_u8
(
ts
->
client
,
GOODIX_READ_COOR_ADDR
,
0
);
return
IRQ_HANDLED
;
}
...
...
@@ -598,7 +549,7 @@ static int goodix_check_cfg(struct goodix_ts_data *ts, const u8 *cfg, int len)
* @cfg: config firmware to write to device
* @len: config data length
*/
static
int
goodix_send_cfg
(
struct
goodix_ts_data
*
ts
,
const
u8
*
cfg
,
int
len
)
int
goodix_send_cfg
(
struct
goodix_ts_data
*
ts
,
const
u8
*
cfg
,
int
len
)
{
int
error
;
...
...
@@ -607,11 +558,9 @@ static int goodix_send_cfg(struct goodix_ts_data *ts, const u8 *cfg, int len)
return
error
;
error
=
goodix_i2c_write
(
ts
->
client
,
ts
->
chip
->
config_addr
,
cfg
,
len
);
if
(
error
)
{
dev_err
(
&
ts
->
client
->
dev
,
"Failed to write config data: %d"
,
error
);
if
(
error
)
return
error
;
}
dev_dbg
(
&
ts
->
client
->
dev
,
"Config sent successfully."
);
/* Let the firmware reconfigure itself, so sleep for 10ms */
...
...
@@ -696,62 +645,82 @@ static int goodix_irq_direction_input(struct goodix_ts_data *ts)
return
-
EINVAL
;
/* Never reached */
}
static
int
goodix_int_sync
(
struct
goodix_ts_data
*
ts
)
int
goodix_int_sync
(
struct
goodix_ts_data
*
ts
)
{
int
error
;
error
=
goodix_irq_direction_output
(
ts
,
0
);
if
(
error
)
return
error
;
goto
error
;
msleep
(
50
);
/* T5: 50ms */
error
=
goodix_irq_direction_input
(
ts
);
if
(
error
)
return
error
;
goto
error
;
return
0
;
error:
dev_err
(
&
ts
->
client
->
dev
,
"Controller irq sync failed.
\n
"
);
return
error
;
}
/**
* goodix_reset
- Reset device during power on
* goodix_reset
_no_int_sync - Reset device, leaving interrupt line in output mode
*
* @ts: goodix_ts_data pointer
*/
static
int
goodix_reset
(
struct
goodix_ts_data
*
ts
)
int
goodix_reset_no_int_sync
(
struct
goodix_ts_data
*
ts
)
{
int
error
;
/* begin select I2C slave addr */
error
=
gpiod_direction_output
(
ts
->
gpiod_rst
,
0
);
if
(
error
)
return
error
;
goto
error
;
msleep
(
20
);
/* T2: > 10ms */
/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */
error
=
goodix_irq_direction_output
(
ts
,
ts
->
client
->
addr
==
0x14
);
if
(
error
)
return
error
;
goto
error
;
usleep_range
(
100
,
2000
);
/* T3: > 100us */
error
=
gpiod_direction_output
(
ts
->
gpiod_rst
,
1
);
if
(
error
)
return
error
;
goto
error
;
usleep_range
(
6000
,
10000
);
/* T4: > 5ms */
/* end select I2C slave addr */
error
=
gpiod_direction_input
(
ts
->
gpiod_rst
);
if
(
error
)
return
error
;
goto
error
;
error
=
goodix_int_sync
(
ts
);
return
0
;
error:
dev_err
(
&
ts
->
client
->
dev
,
"Controller reset failed.
\n
"
);
return
error
;
}
/**
* goodix_reset - Reset device during power on
*
* @ts: goodix_ts_data pointer
*/
static
int
goodix_reset
(
struct
goodix_ts_data
*
ts
)
{
int
error
;
error
=
goodix_reset_no_int_sync
(
ts
);
if
(
error
)
return
error
;
return
0
;
return
goodix_int_sync
(
ts
)
;
}
#ifdef ACPI_GPIO_SUPPORT
...
...
@@ -976,14 +945,19 @@ static void goodix_read_config(struct goodix_ts_data *ts)
int
x_max
,
y_max
;
int
error
;
error
=
goodix_i2c_read
(
ts
->
client
,
ts
->
chip
->
config_addr
,
ts
->
config
,
ts
->
chip
->
config_len
);
if
(
error
)
{
dev_warn
(
&
ts
->
client
->
dev
,
"Error reading config: %d
\n
"
,
error
);
ts
->
int_trigger_type
=
GOODIX_INT_TRIGGER
;
ts
->
max_touch_num
=
GOODIX_MAX_CONTACTS
;
return
;
/*
* On controllers where we need to upload the firmware
* (controllers without flash) ts->config already has the config
* at this point and the controller itself does not have it yet!
*/
if
(
!
ts
->
firmware_name
)
{
error
=
goodix_i2c_read
(
ts
->
client
,
ts
->
chip
->
config_addr
,
ts
->
config
,
ts
->
chip
->
config_len
);
if
(
error
)
{
ts
->
int_trigger_type
=
GOODIX_INT_TRIGGER
;
ts
->
max_touch_num
=
GOODIX_MAX_CONTACTS
;
return
;
}
}
ts
->
int_trigger_type
=
ts
->
config
[
TRIGGER_LOC
]
&
0x03
;
...
...
@@ -1011,10 +985,8 @@ static int goodix_read_version(struct goodix_ts_data *ts)
char
id_str
[
GOODIX_ID_MAX_LEN
+
1
];
error
=
goodix_i2c_read
(
ts
->
client
,
GOODIX_REG_ID
,
buf
,
sizeof
(
buf
));
if
(
error
)
{
dev_err
(
&
ts
->
client
->
dev
,
"read version failed: %d
\n
"
,
error
);
if
(
error
)
return
error
;
}
memcpy
(
id_str
,
buf
,
GOODIX_ID_MAX_LEN
);
id_str
[
GOODIX_ID_MAX_LEN
]
=
0
;
...
...
@@ -1040,13 +1012,10 @@ static int goodix_i2c_test(struct i2c_client *client)
u8
test
;
while
(
retry
++
<
2
)
{
error
=
goodix_i2c_read
(
client
,
GOODIX_REG_ID
,
&
test
,
1
);
error
=
goodix_i2c_read
(
client
,
GOODIX_REG_ID
,
&
test
,
1
);
if
(
!
error
)
return
0
;
dev_err
(
&
client
->
dev
,
"i2c test failed attempt %d: %d
\n
"
,
retry
,
error
);
msleep
(
20
);
}
...
...
@@ -1182,7 +1151,16 @@ static void goodix_config_cb(const struct firmware *cfg, void *ctx)
struct
goodix_ts_data
*
ts
=
ctx
;
int
error
;
if
(
cfg
)
{
if
(
ts
->
firmware_name
)
{
if
(
!
cfg
)
goto
err_release_cfg
;
error
=
goodix_check_cfg
(
ts
,
cfg
->
data
,
cfg
->
size
);
if
(
error
)
goto
err_release_cfg
;
memcpy
(
ts
->
config
,
cfg
->
data
,
cfg
->
size
);
}
else
if
(
cfg
)
{
/* send device configuration to the firmware */
error
=
goodix_send_cfg
(
ts
,
cfg
->
data
,
cfg
->
size
);
if
(
error
)
...
...
@@ -1208,6 +1186,7 @@ static int goodix_ts_probe(struct i2c_client *client,
const
struct
i2c_device_id
*
id
)
{
struct
goodix_ts_data
*
ts
;
const
char
*
cfg_name
;
int
error
;
dev_dbg
(
&
client
->
dev
,
"I2C Address: 0x%02x
\n
"
,
client
->
addr
);
...
...
@@ -1257,10 +1236,8 @@ static int goodix_ts_probe(struct i2c_client *client,
if
(
ts
->
reset_controller_at_probe
)
{
/* reset the controller */
error
=
goodix_reset
(
ts
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"Controller reset failed.
\n
"
);
if
(
error
)
return
error
;
}
}
error
=
goodix_i2c_test
(
client
);
...
...
@@ -1275,20 +1252,27 @@ static int goodix_ts_probe(struct i2c_client *client,
return
error
;
}
error
=
goodix_firmware_check
(
ts
);
if
(
error
)
return
error
;
error
=
goodix_read_version
(
ts
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"Read version failed.
\n
"
);
if
(
error
)
return
error
;
}
ts
->
chip
=
goodix_get_chip_data
(
ts
->
id
);
if
(
ts
->
load_cfg_from_disk
)
{
/* update device config */
ts
->
cfg_name
=
devm_kasprintf
(
&
client
->
dev
,
GFP_KERNEL
,
"goodix_%s_cfg.bin"
,
ts
->
id
);
if
(
!
ts
->
cfg_name
)
return
-
ENOMEM
;
error
=
device_property_read_string
(
&
client
->
dev
,
"goodix,config-name"
,
&
cfg_name
);
if
(
!
error
)
snprintf
(
ts
->
cfg_name
,
sizeof
(
ts
->
cfg_name
),
"goodix/%s"
,
cfg_name
);
else
snprintf
(
ts
->
cfg_name
,
sizeof
(
ts
->
cfg_name
),
"goodix_%s_cfg.bin"
,
ts
->
id
);
error
=
request_firmware_nowait
(
THIS_MODULE
,
true
,
ts
->
cfg_name
,
&
client
->
dev
,
GFP_KERNEL
,
ts
,
...
...
@@ -1338,6 +1322,9 @@ static int __maybe_unused goodix_suspend(struct device *dev)
/* Free IRQ as IRQ pin is used as output in the suspend sequence */
goodix_free_irq
(
ts
);
/* Save reference (calibration) info if necessary */
goodix_save_bak_ref
(
ts
);
/* Output LOW on the INT pin for 5 ms */
error
=
goodix_irq_direction_output
(
ts
,
0
);
if
(
error
)
{
...
...
@@ -1350,7 +1337,6 @@ static int __maybe_unused goodix_suspend(struct device *dev)
error
=
goodix_i2c_write_u8
(
ts
->
client
,
GOODIX_REG_COMMAND
,
GOODIX_CMD_SCREEN_OFF
);
if
(
error
)
{
dev_err
(
&
ts
->
client
->
dev
,
"Screen off command failed
\n
"
);
goodix_irq_direction_input
(
ts
);
goodix_request_irq
(
ts
);
return
-
EAGAIN
;
...
...
@@ -1393,19 +1379,14 @@ static int __maybe_unused goodix_resume(struct device *dev)
error
=
goodix_i2c_read
(
ts
->
client
,
ts
->
chip
->
config_addr
,
&
config_ver
,
1
);
if
(
error
)
dev_warn
(
dev
,
"Error reading config version: %d, resetting controller
\n
"
,
error
);
else
if
(
config_ver
!=
ts
->
config
[
0
])
if
(
!
error
&&
config_ver
!=
ts
->
config
[
0
])
dev_info
(
dev
,
"Config version mismatch %d != %d, resetting controller
\n
"
,
config_ver
,
ts
->
config
[
0
]);
if
(
error
!=
0
||
config_ver
!=
ts
->
config
[
0
])
{
error
=
goodix_reset
(
ts
);
if
(
error
)
{
dev_err
(
dev
,
"Controller reset failed.
\n
"
);
if
(
error
)
return
error
;
}
error
=
goodix_send_cfg
(
ts
,
ts
->
config
,
ts
->
chip
->
config_len
);
if
(
error
)
...
...
drivers/input/touchscreen/goodix.h
0 → 100644
浏览文件 @
efe6f16c
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __GOODIX_H__
#define __GOODIX_H__
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
#include <linux/regulator/consumer.h>
/* Register defines */
#define GOODIX_REG_MISCTL_DSP_CTL 0x4010
#define GOODIX_REG_MISCTL_SRAM_BANK 0x4048
#define GOODIX_REG_MISCTL_MEM_CD_EN 0x4049
#define GOODIX_REG_MISCTL_CACHE_EN 0x404B
#define GOODIX_REG_MISCTL_TMR0_EN 0x40B0
#define GOODIX_REG_MISCTL_SWRST 0x4180
#define GOODIX_REG_MISCTL_CPU_SWRST_PULSE 0x4184
#define GOODIX_REG_MISCTL_BOOTCTL 0x4190
#define GOODIX_REG_MISCTL_BOOT_OPT 0x4218
#define GOODIX_REG_MISCTL_BOOT_CTL 0x5094
#define GOODIX_REG_FW_SIG 0x8000
#define GOODIX_FW_SIG_LEN 10
#define GOODIX_REG_MAIN_CLK 0x8020
#define GOODIX_MAIN_CLK_LEN 6
#define GOODIX_REG_COMMAND 0x8040
#define GOODIX_CMD_SCREEN_OFF 0x05
#define GOODIX_REG_SW_WDT 0x8041
#define GOODIX_REG_REQUEST 0x8043
#define GOODIX_RQST_RESPONDED 0x00
#define GOODIX_RQST_CONFIG 0x01
#define GOODIX_RQST_BAK_REF 0x02
#define GOODIX_RQST_RESET 0x03
#define GOODIX_RQST_MAIN_CLOCK 0x04
/*
* Unknown request which gets send by the controller aprox.
* every 34 seconds once it is up and running.
*/
#define GOODIX_RQST_UNKNOWN 0x06
#define GOODIX_RQST_IDLE 0xFF
#define GOODIX_REG_STATUS 0x8044
#define GOODIX_GT1X_REG_CONFIG_DATA 0x8050
#define GOODIX_GT9X_REG_CONFIG_DATA 0x8047
#define GOODIX_REG_ID 0x8140
#define GOODIX_READ_COOR_ADDR 0x814E
#define GOODIX_REG_BAK_REF 0x99D0
#define GOODIX_ID_MAX_LEN 4
#define GOODIX_CONFIG_MAX_LENGTH 240
#define GOODIX_MAX_KEYS 7
enum
goodix_irq_pin_access_method
{
IRQ_PIN_ACCESS_NONE
,
IRQ_PIN_ACCESS_GPIO
,
IRQ_PIN_ACCESS_ACPI_GPIO
,
IRQ_PIN_ACCESS_ACPI_METHOD
,
};
struct
goodix_ts_data
;
struct
goodix_chip_data
{
u16
config_addr
;
int
config_len
;
int
(
*
check_config
)(
struct
goodix_ts_data
*
ts
,
const
u8
*
cfg
,
int
len
);
void
(
*
calc_config_checksum
)(
struct
goodix_ts_data
*
ts
);
};
struct
goodix_ts_data
{
struct
i2c_client
*
client
;
struct
input_dev
*
input_dev
;
const
struct
goodix_chip_data
*
chip
;
const
char
*
firmware_name
;
struct
touchscreen_properties
prop
;
unsigned
int
max_touch_num
;
unsigned
int
int_trigger_type
;
struct
regulator
*
avdd28
;
struct
regulator
*
vddio
;
struct
gpio_desc
*
gpiod_int
;
struct
gpio_desc
*
gpiod_rst
;
int
gpio_count
;
int
gpio_int_idx
;
char
id
[
GOODIX_ID_MAX_LEN
+
1
];
char
cfg_name
[
64
];
u16
version
;
bool
reset_controller_at_probe
;
bool
load_cfg_from_disk
;
struct
completion
firmware_loading_complete
;
unsigned
long
irq_flags
;
enum
goodix_irq_pin_access_method
irq_pin_access_method
;
unsigned
int
contact_size
;
u8
config
[
GOODIX_CONFIG_MAX_LENGTH
];
unsigned
short
keymap
[
GOODIX_MAX_KEYS
];
u8
main_clk
[
GOODIX_MAIN_CLK_LEN
];
int
bak_ref_len
;
u8
*
bak_ref
;
};
int
goodix_i2c_read
(
struct
i2c_client
*
client
,
u16
reg
,
u8
*
buf
,
int
len
);
int
goodix_i2c_write
(
struct
i2c_client
*
client
,
u16
reg
,
const
u8
*
buf
,
int
len
);
int
goodix_i2c_write_u8
(
struct
i2c_client
*
client
,
u16
reg
,
u8
value
);
int
goodix_send_cfg
(
struct
goodix_ts_data
*
ts
,
const
u8
*
cfg
,
int
len
);
int
goodix_int_sync
(
struct
goodix_ts_data
*
ts
);
int
goodix_reset_no_int_sync
(
struct
goodix_ts_data
*
ts
);
int
goodix_firmware_check
(
struct
goodix_ts_data
*
ts
);
bool
goodix_handle_fw_request
(
struct
goodix_ts_data
*
ts
);
void
goodix_save_bak_ref
(
struct
goodix_ts_data
*
ts
);
#endif
drivers/input/touchscreen/goodix_fwupload.c
0 → 100644
浏览文件 @
efe6f16c
// SPDX-License-Identifier: GPL-2.0-only
/*
* Goodix Touchscreen firmware upload support
*
* Copyright (c) 2021 Hans de Goede <hdegoede@redhat.com>
*
* This is a rewrite of gt9xx_update.c from the Allwinner H3 BSP which is:
* Copyright (c) 2010 - 2012 Goodix Technology.
* Author: andrew@goodix.com
*/
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/i2c.h>
#include "goodix.h"
#define GOODIX_FW_HEADER_LENGTH sizeof(struct goodix_fw_header)
#define GOODIX_FW_SECTION_LENGTH 0x2000
#define GOODIX_FW_DSP_LENGTH 0x1000
#define GOODIX_FW_UPLOAD_ADDRESS 0xc000
#define GOODIX_CFG_LOC_HAVE_KEY 7
#define GOODIX_CFG_LOC_DRVA_NUM 27
#define GOODIX_CFG_LOC_DRVB_NUM 28
#define GOODIX_CFG_LOC_SENS_NUM 29
struct
goodix_fw_header
{
u8
hw_info
[
4
];
u8
pid
[
8
];
u8
vid
[
2
];
}
__packed
;
static
u16
goodix_firmware_checksum
(
const
u8
*
data
,
int
size
)
{
u16
checksum
=
0
;
int
i
;
for
(
i
=
0
;
i
<
size
;
i
+=
2
)
checksum
+=
(
data
[
i
]
<<
8
)
+
data
[
i
+
1
];
return
checksum
;
}
static
int
goodix_firmware_verify
(
struct
device
*
dev
,
const
struct
firmware
*
fw
)
{
const
struct
goodix_fw_header
*
fw_header
;
size_t
expected_size
;
const
u8
*
data
;
u16
checksum
;
char
buf
[
9
];
expected_size
=
GOODIX_FW_HEADER_LENGTH
+
4
*
GOODIX_FW_SECTION_LENGTH
+
GOODIX_FW_DSP_LENGTH
;
if
(
fw
->
size
!=
expected_size
)
{
dev_err
(
dev
,
"Firmware has wrong size, expected %zu got %zu
\n
"
,
expected_size
,
fw
->
size
);
return
-
EINVAL
;
}
data
=
fw
->
data
+
GOODIX_FW_HEADER_LENGTH
;
checksum
=
goodix_firmware_checksum
(
data
,
4
*
GOODIX_FW_SECTION_LENGTH
);
if
(
checksum
)
{
dev_err
(
dev
,
"Main firmware checksum error
\n
"
);
return
-
EINVAL
;
}
data
+=
4
*
GOODIX_FW_SECTION_LENGTH
;
checksum
=
goodix_firmware_checksum
(
data
,
GOODIX_FW_DSP_LENGTH
);
if
(
checksum
)
{
dev_err
(
dev
,
"DSP firmware checksum error
\n
"
);
return
-
EINVAL
;
}
fw_header
=
(
const
struct
goodix_fw_header
*
)
fw
->
data
;
dev_info
(
dev
,
"Firmware hardware info %02x%02x%02x%02x
\n
"
,
fw_header
->
hw_info
[
0
],
fw_header
->
hw_info
[
1
],
fw_header
->
hw_info
[
2
],
fw_header
->
hw_info
[
3
]);
/* pid is a 8 byte buffer containing a string, weird I know */
memcpy
(
buf
,
fw_header
->
pid
,
8
);
buf
[
8
]
=
0
;
dev_info
(
dev
,
"Firmware PID: %s VID: %02x%02x
\n
"
,
buf
,
fw_header
->
vid
[
0
],
fw_header
->
vid
[
1
]);
return
0
;
}
static
int
goodix_enter_upload_mode
(
struct
i2c_client
*
client
)
{
int
tries
,
error
;
u8
val
;
tries
=
200
;
do
{
error
=
goodix_i2c_write_u8
(
client
,
GOODIX_REG_MISCTL_SWRST
,
0x0c
);
if
(
error
)
return
error
;
error
=
goodix_i2c_read
(
client
,
GOODIX_REG_MISCTL_SWRST
,
&
val
,
1
);
if
(
error
)
return
error
;
if
(
val
==
0x0c
)
break
;
}
while
(
--
tries
);
if
(
!
tries
)
{
dev_err
(
&
client
->
dev
,
"Error could not hold ss51 & dsp
\n
"
);
return
-
EIO
;
}
/* DSP_CK and DSP_ALU_CK PowerOn */
error
=
goodix_i2c_write_u8
(
client
,
GOODIX_REG_MISCTL_DSP_CTL
,
0x00
);
if
(
error
)
return
error
;
/* Disable watchdog */
error
=
goodix_i2c_write_u8
(
client
,
GOODIX_REG_MISCTL_TMR0_EN
,
0x00
);
if
(
error
)
return
error
;
/* Clear cache enable */
error
=
goodix_i2c_write_u8
(
client
,
GOODIX_REG_MISCTL_CACHE_EN
,
0x00
);
if
(
error
)
return
error
;
/* Set boot from SRAM */
error
=
goodix_i2c_write_u8
(
client
,
GOODIX_REG_MISCTL_BOOTCTL
,
0x02
);
if
(
error
)
return
error
;
/* Software reboot */
error
=
goodix_i2c_write_u8
(
client
,
GOODIX_REG_MISCTL_CPU_SWRST_PULSE
,
0x01
);
if
(
error
)
return
error
;
/* Clear control flag */
error
=
goodix_i2c_write_u8
(
client
,
GOODIX_REG_MISCTL_BOOTCTL
,
0x00
);
if
(
error
)
return
error
;
/* Set scramble */
error
=
goodix_i2c_write_u8
(
client
,
GOODIX_REG_MISCTL_BOOT_OPT
,
0x00
);
if
(
error
)
return
error
;
/* Enable accessing code */
error
=
goodix_i2c_write_u8
(
client
,
GOODIX_REG_MISCTL_MEM_CD_EN
,
0x01
);
if
(
error
)
return
error
;
return
0
;
}
static
int
goodix_start_firmware
(
struct
i2c_client
*
client
)
{
int
error
;
u8
val
;
/* Init software watchdog */
error
=
goodix_i2c_write_u8
(
client
,
GOODIX_REG_SW_WDT
,
0xaa
);
if
(
error
)
return
error
;
/* Release SS51 & DSP */
error
=
goodix_i2c_write_u8
(
client
,
GOODIX_REG_MISCTL_SWRST
,
0x00
);
if
(
error
)
return
error
;
error
=
goodix_i2c_read
(
client
,
GOODIX_REG_SW_WDT
,
&
val
,
1
);
if
(
error
)
return
error
;
/* The value we've written to SW_WDT should have been cleared now */
if
(
val
==
0xaa
)
{
dev_err
(
&
client
->
dev
,
"Error SW_WDT reg not cleared on fw startup
\n
"
);
return
-
EIO
;
}
/* Re-init software watchdog */
error
=
goodix_i2c_write_u8
(
client
,
GOODIX_REG_SW_WDT
,
0xaa
);
if
(
error
)
return
error
;
return
0
;
}
static
int
goodix_firmware_upload
(
struct
goodix_ts_data
*
ts
)
{
const
struct
firmware
*
fw
;
char
fw_name
[
64
];
const
u8
*
data
;
int
error
;
snprintf
(
fw_name
,
sizeof
(
fw_name
),
"goodix/%s"
,
ts
->
firmware_name
);
error
=
request_firmware
(
&
fw
,
fw_name
,
&
ts
->
client
->
dev
);
if
(
error
)
{
dev_err
(
&
ts
->
client
->
dev
,
"Firmware request error %d
\n
"
,
error
);
return
error
;
}
error
=
goodix_firmware_verify
(
&
ts
->
client
->
dev
,
fw
);
if
(
error
)
goto
release
;
error
=
goodix_reset_no_int_sync
(
ts
);
if
(
error
)
return
error
;
error
=
goodix_enter_upload_mode
(
ts
->
client
);
if
(
error
)
goto
release
;
/* Select SRAM bank 0 and upload section 1 & 2 */
error
=
goodix_i2c_write_u8
(
ts
->
client
,
GOODIX_REG_MISCTL_SRAM_BANK
,
0x00
);
if
(
error
)
goto
release
;
data
=
fw
->
data
+
GOODIX_FW_HEADER_LENGTH
;
error
=
goodix_i2c_write
(
ts
->
client
,
GOODIX_FW_UPLOAD_ADDRESS
,
data
,
2
*
GOODIX_FW_SECTION_LENGTH
);
if
(
error
)
goto
release
;
/* Select SRAM bank 1 and upload section 3 & 4 */
error
=
goodix_i2c_write_u8
(
ts
->
client
,
GOODIX_REG_MISCTL_SRAM_BANK
,
0x01
);
if
(
error
)
goto
release
;
data
+=
2
*
GOODIX_FW_SECTION_LENGTH
;
error
=
goodix_i2c_write
(
ts
->
client
,
GOODIX_FW_UPLOAD_ADDRESS
,
data
,
2
*
GOODIX_FW_SECTION_LENGTH
);
if
(
error
)
goto
release
;
/* Select SRAM bank 2 and upload the DSP firmware */
error
=
goodix_i2c_write_u8
(
ts
->
client
,
GOODIX_REG_MISCTL_SRAM_BANK
,
0x02
);
if
(
error
)
goto
release
;
data
+=
2
*
GOODIX_FW_SECTION_LENGTH
;
error
=
goodix_i2c_write
(
ts
->
client
,
GOODIX_FW_UPLOAD_ADDRESS
,
data
,
GOODIX_FW_DSP_LENGTH
);
if
(
error
)
goto
release
;
error
=
goodix_start_firmware
(
ts
->
client
);
if
(
error
)
goto
release
;
error
=
goodix_int_sync
(
ts
);
release:
release_firmware
(
fw
);
return
error
;
}
static
int
goodix_prepare_bak_ref
(
struct
goodix_ts_data
*
ts
)
{
u8
have_key
,
driver_num
,
sensor_num
;
if
(
ts
->
bak_ref
)
return
0
;
/* Already done */
have_key
=
(
ts
->
config
[
GOODIX_CFG_LOC_HAVE_KEY
]
&
0x01
);
driver_num
=
(
ts
->
config
[
GOODIX_CFG_LOC_DRVA_NUM
]
&
0x1f
)
+
(
ts
->
config
[
GOODIX_CFG_LOC_DRVB_NUM
]
&
0x1f
);
if
(
have_key
)
driver_num
--
;
sensor_num
=
(
ts
->
config
[
GOODIX_CFG_LOC_SENS_NUM
]
&
0x0f
)
+
((
ts
->
config
[
GOODIX_CFG_LOC_SENS_NUM
]
>>
4
)
&
0x0f
);
dev_dbg
(
&
ts
->
client
->
dev
,
"Drv %d Sen %d Key %d
\n
"
,
driver_num
,
sensor_num
,
have_key
);
ts
->
bak_ref_len
=
(
driver_num
*
(
sensor_num
-
2
)
+
2
)
*
2
;
ts
->
bak_ref
=
devm_kzalloc
(
&
ts
->
client
->
dev
,
ts
->
bak_ref_len
,
GFP_KERNEL
);
if
(
!
ts
->
bak_ref
)
return
-
ENOMEM
;
/*
* The bak_ref array contains the backup of an array of (self/auto)
* calibration related values which the Android version of the driver
* stores on the filesystem so that it can be restored after reboot.
* The mainline kernel never writes directly to the filesystem like
* this, we always start will all the values which give a correction
* factor in approx. the -20 - +20 range (in 2s complement) set to 0.
*
* Note the touchscreen works fine without restoring the reference
* values after a reboot / power-cycle.
*
* The last 2 bytes are a 16 bits unsigned checksum which is expected
* to make the addition al all 16 bit unsigned values in the array add
* up to 1 (rather then the usual 0), so we must set the last byte to 1.
*/
ts
->
bak_ref
[
ts
->
bak_ref_len
-
1
]
=
1
;
return
0
;
}
static
int
goodix_send_main_clock
(
struct
goodix_ts_data
*
ts
)
{
u32
main_clk
=
54
;
/* Default main clock */
u8
checksum
=
0
;
int
i
;
device_property_read_u32
(
&
ts
->
client
->
dev
,
"goodix,main-clk"
,
&
main_clk
);
for
(
i
=
0
;
i
<
(
GOODIX_MAIN_CLK_LEN
-
1
);
i
++
)
{
ts
->
main_clk
[
i
]
=
main_clk
;
checksum
+=
main_clk
;
}
/* The value of all bytes combines must be 0 */
ts
->
main_clk
[
GOODIX_MAIN_CLK_LEN
-
1
]
=
256
-
checksum
;
return
goodix_i2c_write
(
ts
->
client
,
GOODIX_REG_MAIN_CLK
,
ts
->
main_clk
,
GOODIX_MAIN_CLK_LEN
);
}
int
goodix_firmware_check
(
struct
goodix_ts_data
*
ts
)
{
device_property_read_string
(
&
ts
->
client
->
dev
,
"firmware-name"
,
&
ts
->
firmware_name
);
if
(
!
ts
->
firmware_name
)
return
0
;
if
(
ts
->
irq_pin_access_method
==
IRQ_PIN_ACCESS_NONE
)
{
dev_err
(
&
ts
->
client
->
dev
,
"Error no IRQ-pin access method, cannot upload fw.
\n
"
);
return
-
EINVAL
;
}
dev_info
(
&
ts
->
client
->
dev
,
"Touchscreen controller needs fw-upload
\n
"
);
ts
->
load_cfg_from_disk
=
true
;
return
goodix_firmware_upload
(
ts
);
}
bool
goodix_handle_fw_request
(
struct
goodix_ts_data
*
ts
)
{
int
error
;
u8
val
;
error
=
goodix_i2c_read
(
ts
->
client
,
GOODIX_REG_REQUEST
,
&
val
,
1
);
if
(
error
)
return
false
;
switch
(
val
)
{
case
GOODIX_RQST_RESPONDED
:
/*
* If we read back our own last ack the IRQ was not for
* a request.
*/
return
false
;
case
GOODIX_RQST_CONFIG
:
error
=
goodix_send_cfg
(
ts
,
ts
->
config
,
ts
->
chip
->
config_len
);
if
(
error
)
return
false
;
break
;
case
GOODIX_RQST_BAK_REF
:
error
=
goodix_prepare_bak_ref
(
ts
);
if
(
error
)
return
false
;
error
=
goodix_i2c_write
(
ts
->
client
,
GOODIX_REG_BAK_REF
,
ts
->
bak_ref
,
ts
->
bak_ref_len
);
if
(
error
)
return
false
;
break
;
case
GOODIX_RQST_RESET
:
error
=
goodix_firmware_upload
(
ts
);
if
(
error
)
return
false
;
break
;
case
GOODIX_RQST_MAIN_CLOCK
:
error
=
goodix_send_main_clock
(
ts
);
if
(
error
)
return
false
;
break
;
case
GOODIX_RQST_UNKNOWN
:
case
GOODIX_RQST_IDLE
:
break
;
default:
dev_err_ratelimited
(
&
ts
->
client
->
dev
,
"Unknown Request: 0x%02x
\n
"
,
val
);
}
/* Ack the request */
goodix_i2c_write_u8
(
ts
->
client
,
GOODIX_REG_REQUEST
,
GOODIX_RQST_RESPONDED
);
return
true
;
}
void
goodix_save_bak_ref
(
struct
goodix_ts_data
*
ts
)
{
int
error
;
u8
val
;
if
(
!
ts
->
firmware_name
)
return
;
error
=
goodix_i2c_read
(
ts
->
client
,
GOODIX_REG_STATUS
,
&
val
,
1
);
if
(
error
)
return
;
if
(
!
(
val
&
0x80
))
return
;
error
=
goodix_i2c_read
(
ts
->
client
,
GOODIX_REG_BAK_REF
,
ts
->
bak_ref
,
ts
->
bak_ref_len
);
if
(
error
)
{
memset
(
ts
->
bak_ref
,
0
,
ts
->
bak_ref_len
);
ts
->
bak_ref
[
ts
->
bak_ref_len
-
1
]
=
1
;
}
}
drivers/input/touchscreen/ili210x.c
浏览文件 @
efe6f16c
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/crc-ccitt.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/ihex.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
...
...
@@ -12,7 +14,7 @@
#include <linux/slab.h>
#include <asm/unaligned.h>
#define ILI2XXX_POLL_PERIOD
20
#define ILI2XXX_POLL_PERIOD
15
#define ILI210X_DATA_SIZE 64
#define ILI211X_DATA_SIZE 43
...
...
@@ -22,8 +24,23 @@
/* Touchscreen commands */
#define REG_TOUCHDATA 0x10
#define REG_PANEL_INFO 0x20
#define REG_FIRMWARE_VERSION 0x40
#define REG_PROTOCOL_VERSION 0x42
#define REG_KERNEL_VERSION 0x61
#define REG_IC_BUSY 0x80
#define REG_IC_BUSY_NOT_BUSY 0x50
#define REG_GET_MODE 0xc0
#define REG_GET_MODE_AP 0x5a
#define REG_GET_MODE_BL 0x55
#define REG_SET_MODE_AP 0xc1
#define REG_SET_MODE_BL 0xc2
#define REG_WRITE_DATA 0xc3
#define REG_WRITE_ENABLE 0xc4
#define REG_READ_DATA_CRC 0xc7
#define REG_CALIBRATE 0xcc
#define ILI251X_FW_FILENAME "ilitek/ili251x.bin"
struct
ili2xxx_chip
{
int
(
*
read_reg
)(
struct
i2c_client
*
client
,
u8
reg
,
void
*
buf
,
size_t
len
);
...
...
@@ -35,6 +52,7 @@ struct ili2xxx_chip {
unsigned
int
max_touches
;
unsigned
int
resolution
;
bool
has_calibrate_reg
;
bool
has_firmware_proto
;
bool
has_pressure_reg
;
};
...
...
@@ -44,6 +62,10 @@ struct ili210x {
struct
gpio_desc
*
reset_gpio
;
struct
touchscreen_properties
prop
;
const
struct
ili2xxx_chip
*
chip
;
u8
version_firmware
[
8
];
u8
version_kernel
[
5
];
u8
version_proto
[
2
];
u8
ic_mode
[
2
];
bool
stop
;
};
...
...
@@ -202,15 +224,17 @@ static const struct ili2xxx_chip ili212x_chip = {
.
has_calibrate_reg
=
true
,
};
static
int
ili251x_read_reg
(
struct
i2c_client
*
client
,
u8
reg
,
void
*
buf
,
size_t
len
)
static
int
ili251x_read_reg_common
(
struct
i2c_client
*
client
,
u8
reg
,
void
*
buf
,
size_t
len
,
unsigned
int
delay
)
{
int
error
;
int
ret
;
ret
=
i2c_master_send
(
client
,
&
reg
,
1
);
if
(
ret
==
1
)
{
usleep_range
(
5000
,
5500
);
if
(
delay
)
usleep_range
(
delay
,
delay
+
500
);
ret
=
i2c_master_recv
(
client
,
buf
,
len
);
if
(
ret
==
len
)
...
...
@@ -222,12 +246,18 @@ static int ili251x_read_reg(struct i2c_client *client,
return
ret
;
}
static
int
ili251x_read_reg
(
struct
i2c_client
*
client
,
u8
reg
,
void
*
buf
,
size_t
len
)
{
return
ili251x_read_reg_common
(
client
,
reg
,
buf
,
len
,
5000
);
}
static
int
ili251x_read_touch_data
(
struct
i2c_client
*
client
,
u8
*
data
)
{
int
error
;
error
=
ili251x_read_reg
(
client
,
REG_TOUCHDATA
,
data
,
ILI251X_DATA_SIZE1
);
error
=
ili251x_read_reg
_common
(
client
,
REG_TOUCHDATA
,
data
,
ILI251X_DATA_SIZE1
,
0
);
if
(
!
error
&&
data
[
0
]
==
2
)
{
error
=
i2c_master_recv
(
client
,
data
+
ILI251X_DATA_SIZE1
,
ILI251X_DATA_SIZE2
);
...
...
@@ -268,6 +298,7 @@ static const struct ili2xxx_chip ili251x_chip = {
.
continue_polling
=
ili251x_check_continue_polling
,
.
max_touches
=
10
,
.
has_calibrate_reg
=
true
,
.
has_firmware_proto
=
true
,
.
has_pressure_reg
=
true
,
};
...
...
@@ -303,10 +334,13 @@ static irqreturn_t ili210x_irq(int irq, void *irq_data)
const
struct
ili2xxx_chip
*
chip
=
priv
->
chip
;
u8
touchdata
[
ILI210X_DATA_SIZE
]
=
{
0
};
bool
keep_polling
;
ktime_t
time_next
;
s64
time_delta
;
bool
touch
;
int
error
;
do
{
time_next
=
ktime_add_ms
(
ktime_get
(),
ILI2XXX_POLL_PERIOD
);
error
=
chip
->
get_touch_data
(
client
,
touchdata
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
...
...
@@ -316,13 +350,201 @@ static irqreturn_t ili210x_irq(int irq, void *irq_data)
touch
=
ili210x_report_events
(
priv
,
touchdata
);
keep_polling
=
chip
->
continue_polling
(
touchdata
,
touch
);
if
(
keep_polling
)
msleep
(
ILI2XXX_POLL_PERIOD
);
if
(
keep_polling
)
{
time_delta
=
ktime_us_delta
(
time_next
,
ktime_get
());
if
(
time_delta
>
0
)
usleep_range
(
time_delta
,
time_delta
+
1000
);
}
}
while
(
!
priv
->
stop
&&
keep_polling
);
return
IRQ_HANDLED
;
}
static
int
ili251x_firmware_update_resolution
(
struct
device
*
dev
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
ili210x
*
priv
=
i2c_get_clientdata
(
client
);
u16
resx
,
resy
;
u8
rs
[
10
];
int
error
;
/* The firmware update blob might have changed the resolution. */
error
=
priv
->
chip
->
read_reg
(
client
,
REG_PANEL_INFO
,
&
rs
,
sizeof
(
rs
));
if
(
error
)
return
error
;
resx
=
le16_to_cpup
((
__le16
*
)
rs
);
resy
=
le16_to_cpup
((
__le16
*
)(
rs
+
2
));
/* The value reported by the firmware is invalid. */
if
(
!
resx
||
resx
==
0xffff
||
!
resy
||
resy
==
0xffff
)
return
-
EINVAL
;
input_abs_set_max
(
priv
->
input
,
ABS_X
,
resx
-
1
);
input_abs_set_max
(
priv
->
input
,
ABS_Y
,
resy
-
1
);
input_abs_set_max
(
priv
->
input
,
ABS_MT_POSITION_X
,
resx
-
1
);
input_abs_set_max
(
priv
->
input
,
ABS_MT_POSITION_Y
,
resy
-
1
);
return
0
;
}
static
ssize_t
ili251x_firmware_update_firmware_version
(
struct
device
*
dev
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
ili210x
*
priv
=
i2c_get_clientdata
(
client
);
int
error
;
u8
fw
[
8
];
/* Get firmware version */
error
=
priv
->
chip
->
read_reg
(
client
,
REG_FIRMWARE_VERSION
,
&
fw
,
sizeof
(
fw
));
if
(
!
error
)
memcpy
(
priv
->
version_firmware
,
fw
,
sizeof
(
fw
));
return
error
;
}
static
ssize_t
ili251x_firmware_update_kernel_version
(
struct
device
*
dev
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
ili210x
*
priv
=
i2c_get_clientdata
(
client
);
int
error
;
u8
kv
[
5
];
/* Get kernel version */
error
=
priv
->
chip
->
read_reg
(
client
,
REG_KERNEL_VERSION
,
&
kv
,
sizeof
(
kv
));
if
(
!
error
)
memcpy
(
priv
->
version_kernel
,
kv
,
sizeof
(
kv
));
return
error
;
}
static
ssize_t
ili251x_firmware_update_protocol_version
(
struct
device
*
dev
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
ili210x
*
priv
=
i2c_get_clientdata
(
client
);
int
error
;
u8
pv
[
2
];
/* Get protocol version */
error
=
priv
->
chip
->
read_reg
(
client
,
REG_PROTOCOL_VERSION
,
&
pv
,
sizeof
(
pv
));
if
(
!
error
)
memcpy
(
priv
->
version_proto
,
pv
,
sizeof
(
pv
));
return
error
;
}
static
ssize_t
ili251x_firmware_update_ic_mode
(
struct
device
*
dev
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
ili210x
*
priv
=
i2c_get_clientdata
(
client
);
int
error
;
u8
md
[
2
];
/* Get chip boot mode */
error
=
priv
->
chip
->
read_reg
(
client
,
REG_GET_MODE
,
&
md
,
sizeof
(
md
));
if
(
!
error
)
memcpy
(
priv
->
ic_mode
,
md
,
sizeof
(
md
));
return
error
;
}
static
int
ili251x_firmware_update_cached_state
(
struct
device
*
dev
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
ili210x
*
priv
=
i2c_get_clientdata
(
client
);
int
error
;
if
(
!
priv
->
chip
->
has_firmware_proto
)
return
0
;
/* Wait for firmware to boot and stabilize itself. */
msleep
(
200
);
/* Firmware does report valid information. */
error
=
ili251x_firmware_update_resolution
(
dev
);
if
(
error
)
return
error
;
error
=
ili251x_firmware_update_firmware_version
(
dev
);
if
(
error
)
return
error
;
error
=
ili251x_firmware_update_kernel_version
(
dev
);
if
(
error
)
return
error
;
error
=
ili251x_firmware_update_protocol_version
(
dev
);
if
(
error
)
return
error
;
error
=
ili251x_firmware_update_ic_mode
(
dev
);
if
(
error
)
return
error
;
return
0
;
}
static
ssize_t
ili251x_firmware_version_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
ili210x
*
priv
=
i2c_get_clientdata
(
client
);
u8
*
fw
=
priv
->
version_firmware
;
return
sysfs_emit
(
buf
,
"%02x%02x.%02x%02x.%02x%02x.%02x%02x
\n
"
,
fw
[
0
],
fw
[
1
],
fw
[
2
],
fw
[
3
],
fw
[
4
],
fw
[
5
],
fw
[
6
],
fw
[
7
]);
}
static
DEVICE_ATTR
(
firmware_version
,
0444
,
ili251x_firmware_version_show
,
NULL
);
static
ssize_t
ili251x_kernel_version_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
ili210x
*
priv
=
i2c_get_clientdata
(
client
);
u8
*
kv
=
priv
->
version_kernel
;
return
sysfs_emit
(
buf
,
"%02x.%02x.%02x.%02x.%02x
\n
"
,
kv
[
0
],
kv
[
1
],
kv
[
2
],
kv
[
3
],
kv
[
4
]);
}
static
DEVICE_ATTR
(
kernel_version
,
0444
,
ili251x_kernel_version_show
,
NULL
);
static
ssize_t
ili251x_protocol_version_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
ili210x
*
priv
=
i2c_get_clientdata
(
client
);
u8
*
pv
=
priv
->
version_proto
;
return
sysfs_emit
(
buf
,
"%02x.%02x
\n
"
,
pv
[
0
],
pv
[
1
]);
}
static
DEVICE_ATTR
(
protocol_version
,
0444
,
ili251x_protocol_version_show
,
NULL
);
static
ssize_t
ili251x_mode_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
ili210x
*
priv
=
i2c_get_clientdata
(
client
);
u8
*
md
=
priv
->
ic_mode
;
char
*
mode
=
"AP"
;
if
(
md
[
0
]
==
REG_GET_MODE_AP
)
/* Application Mode */
mode
=
"AP"
;
else
if
(
md
[
0
]
==
REG_GET_MODE_BL
)
/* BootLoader Mode */
mode
=
"BL"
;
else
/* Unknown Mode */
mode
=
"??"
;
return
sysfs_emit
(
buf
,
"%02x.%02x:%s
\n
"
,
md
[
0
],
md
[
1
],
mode
);
}
static
DEVICE_ATTR
(
mode
,
0444
,
ili251x_mode_show
,
NULL
);
static
ssize_t
ili210x_calibrate
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
...
...
@@ -349,24 +571,333 @@ static ssize_t ili210x_calibrate(struct device *dev,
}
static
DEVICE_ATTR
(
calibrate
,
S_IWUSR
,
NULL
,
ili210x_calibrate
);
static
int
ili251x_firmware_to_buffer
(
const
struct
firmware
*
fw
,
u8
**
buf
,
u16
*
ac_end
,
u16
*
df_end
)
{
const
struct
ihex_binrec
*
rec
;
u32
fw_addr
,
fw_last_addr
=
0
;
u16
fw_len
;
u8
*
fw_buf
;
int
error
;
/*
* The firmware ihex blob can never be bigger than 64 kiB, so make this
* simple -- allocate a 64 kiB buffer, iterate over the ihex blob records
* once, copy them all into this buffer at the right locations, and then
* do all operations on this linear buffer.
*/
fw_buf
=
kzalloc
(
SZ_64K
,
GFP_KERNEL
);
if
(
!
fw_buf
)
return
-
ENOMEM
;
rec
=
(
const
struct
ihex_binrec
*
)
fw
->
data
;
while
(
rec
)
{
fw_addr
=
be32_to_cpu
(
rec
->
addr
);
fw_len
=
be16_to_cpu
(
rec
->
len
);
/* The last 32 Byte firmware block can be 0xffe0 */
if
(
fw_addr
+
fw_len
>
SZ_64K
||
fw_addr
>
SZ_64K
-
32
)
{
error
=
-
EFBIG
;
goto
err_big
;
}
/* Find the last address before DF start address, that is AC end */
if
(
fw_addr
==
0xf000
)
*
ac_end
=
fw_last_addr
;
fw_last_addr
=
fw_addr
+
fw_len
;
memcpy
(
fw_buf
+
fw_addr
,
rec
->
data
,
fw_len
);
rec
=
ihex_next_binrec
(
rec
);
}
/* DF end address is the last address in the firmware blob */
*
df_end
=
fw_addr
+
fw_len
;
*
buf
=
fw_buf
;
return
0
;
err_big:
kfree
(
fw_buf
);
return
error
;
}
/* Switch mode between Application and BootLoader */
static
int
ili251x_switch_ic_mode
(
struct
i2c_client
*
client
,
u8
cmd_mode
)
{
struct
ili210x
*
priv
=
i2c_get_clientdata
(
client
);
u8
cmd_wren
[
3
]
=
{
REG_WRITE_ENABLE
,
0x5a
,
0xa5
};
u8
md
[
2
];
int
error
;
error
=
priv
->
chip
->
read_reg
(
client
,
REG_GET_MODE
,
md
,
sizeof
(
md
));
if
(
error
)
return
error
;
/* Mode already set */
if
((
cmd_mode
==
REG_SET_MODE_AP
&&
md
[
0
]
==
REG_GET_MODE_AP
)
||
(
cmd_mode
==
REG_SET_MODE_BL
&&
md
[
0
]
==
REG_GET_MODE_BL
))
return
0
;
/* Unlock writes */
error
=
i2c_master_send
(
client
,
cmd_wren
,
sizeof
(
cmd_wren
));
if
(
error
!=
sizeof
(
cmd_wren
))
return
-
EINVAL
;
mdelay
(
20
);
/* Select mode (BootLoader or Application) */
error
=
i2c_master_send
(
client
,
&
cmd_mode
,
1
);
if
(
error
!=
1
)
return
-
EINVAL
;
mdelay
(
200
);
/* Reboot into bootloader takes a lot of time ... */
/* Read back mode */
error
=
priv
->
chip
->
read_reg
(
client
,
REG_GET_MODE
,
md
,
sizeof
(
md
));
if
(
error
)
return
error
;
/* Check if mode is correct now. */
if
((
cmd_mode
==
REG_SET_MODE_AP
&&
md
[
0
]
==
REG_GET_MODE_AP
)
||
(
cmd_mode
==
REG_SET_MODE_BL
&&
md
[
0
]
==
REG_GET_MODE_BL
))
return
0
;
return
-
EINVAL
;
}
static
int
ili251x_firmware_busy
(
struct
i2c_client
*
client
)
{
struct
ili210x
*
priv
=
i2c_get_clientdata
(
client
);
int
error
,
i
=
0
;
u8
data
;
do
{
/* The read_reg already contains suitable delay */
error
=
priv
->
chip
->
read_reg
(
client
,
REG_IC_BUSY
,
&
data
,
1
);
if
(
error
)
return
error
;
if
(
i
++
==
100000
)
return
-
ETIMEDOUT
;
}
while
(
data
!=
REG_IC_BUSY_NOT_BUSY
);
return
0
;
}
static
int
ili251x_firmware_write_to_ic
(
struct
device
*
dev
,
u8
*
fwbuf
,
u16
start
,
u16
end
,
u8
dataflash
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
ili210x
*
priv
=
i2c_get_clientdata
(
client
);
u8
cmd_crc
=
REG_READ_DATA_CRC
;
u8
crcrb
[
4
]
=
{
0
};
u8
fw_data
[
33
];
u16
fw_addr
;
int
error
;
/*
* The DF (dataflash) needs 2 bytes offset for unknown reasons,
* the AC (application) has 2 bytes CRC16-CCITT at the end.
*/
u16
crc
=
crc_ccitt
(
0
,
fwbuf
+
start
+
(
dataflash
?
2
:
0
),
end
-
start
-
2
);
/* Unlock write to either AC (application) or DF (dataflash) area */
u8
cmd_wr
[
10
]
=
{
REG_WRITE_ENABLE
,
0x5a
,
0xa5
,
dataflash
,
(
end
>>
16
)
&
0xff
,
(
end
>>
8
)
&
0xff
,
end
&
0xff
,
(
crc
>>
16
)
&
0xff
,
(
crc
>>
8
)
&
0xff
,
crc
&
0xff
};
error
=
i2c_master_send
(
client
,
cmd_wr
,
sizeof
(
cmd_wr
));
if
(
error
!=
sizeof
(
cmd_wr
))
return
-
EINVAL
;
error
=
ili251x_firmware_busy
(
client
);
if
(
error
)
return
error
;
for
(
fw_addr
=
start
;
fw_addr
<
end
;
fw_addr
+=
32
)
{
fw_data
[
0
]
=
REG_WRITE_DATA
;
memcpy
(
&
(
fw_data
[
1
]),
fwbuf
+
fw_addr
,
32
);
error
=
i2c_master_send
(
client
,
fw_data
,
33
);
if
(
error
!=
sizeof
(
fw_data
))
return
error
;
error
=
ili251x_firmware_busy
(
client
);
if
(
error
)
return
error
;
}
error
=
i2c_master_send
(
client
,
&
cmd_crc
,
1
);
if
(
error
!=
1
)
return
-
EINVAL
;
error
=
ili251x_firmware_busy
(
client
);
if
(
error
)
return
error
;
error
=
priv
->
chip
->
read_reg
(
client
,
REG_READ_DATA_CRC
,
&
crcrb
,
sizeof
(
crcrb
));
if
(
error
)
return
error
;
/* Check CRC readback */
if
((
crcrb
[
0
]
!=
(
crc
&
0xff
))
||
crcrb
[
1
]
!=
((
crc
>>
8
)
&
0xff
))
return
-
EINVAL
;
return
0
;
}
static
int
ili251x_firmware_reset
(
struct
i2c_client
*
client
)
{
u8
cmd_reset
[
2
]
=
{
0xf2
,
0x01
};
int
error
;
error
=
i2c_master_send
(
client
,
cmd_reset
,
sizeof
(
cmd_reset
));
if
(
error
!=
sizeof
(
cmd_reset
))
return
-
EINVAL
;
return
ili251x_firmware_busy
(
client
);
}
static
void
ili251x_hardware_reset
(
struct
device
*
dev
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
ili210x
*
priv
=
i2c_get_clientdata
(
client
);
/* Reset the controller */
gpiod_set_value_cansleep
(
priv
->
reset_gpio
,
1
);
usleep_range
(
10000
,
15000
);
gpiod_set_value_cansleep
(
priv
->
reset_gpio
,
0
);
msleep
(
300
);
}
static
ssize_t
ili210x_firmware_update_store
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
const
char
*
fwname
=
ILI251X_FW_FILENAME
;
const
struct
firmware
*
fw
;
u16
ac_end
,
df_end
;
u8
*
fwbuf
;
int
error
;
int
i
;
error
=
request_ihex_firmware
(
&
fw
,
fwname
,
dev
);
if
(
error
)
{
dev_err
(
dev
,
"Failed to request firmware %s, error=%d
\n
"
,
fwname
,
error
);
return
error
;
}
error
=
ili251x_firmware_to_buffer
(
fw
,
&
fwbuf
,
&
ac_end
,
&
df_end
);
release_firmware
(
fw
);
if
(
error
)
return
error
;
/*
* Disable touchscreen IRQ, so that we would not get spurious touch
* interrupt during firmware update, and so that the IRQ handler won't
* trigger and interfere with the firmware update. There is no bit in
* the touch controller to disable the IRQs during update, so we have
* to do it this way here.
*/
disable_irq
(
client
->
irq
);
dev_dbg
(
dev
,
"Firmware update started, firmware=%s
\n
"
,
fwname
);
ili251x_hardware_reset
(
dev
);
error
=
ili251x_firmware_reset
(
client
);
if
(
error
)
goto
exit
;
/* This may not succeed on first try, so re-try a few times. */
for
(
i
=
0
;
i
<
5
;
i
++
)
{
error
=
ili251x_switch_ic_mode
(
client
,
REG_SET_MODE_BL
);
if
(
!
error
)
break
;
}
if
(
error
)
goto
exit
;
dev_dbg
(
dev
,
"IC is now in BootLoader mode
\n
"
);
msleep
(
200
);
/* The bootloader seems to need some time too. */
error
=
ili251x_firmware_write_to_ic
(
dev
,
fwbuf
,
0xf000
,
df_end
,
1
);
if
(
error
)
{
dev_err
(
dev
,
"DF firmware update failed, error=%d
\n
"
,
error
);
goto
exit
;
}
dev_dbg
(
dev
,
"DataFlash firmware written
\n
"
);
error
=
ili251x_firmware_write_to_ic
(
dev
,
fwbuf
,
0x2000
,
ac_end
,
0
);
if
(
error
)
{
dev_err
(
dev
,
"AC firmware update failed, error=%d
\n
"
,
error
);
goto
exit
;
}
dev_dbg
(
dev
,
"Application firmware written
\n
"
);
/* This may not succeed on first try, so re-try a few times. */
for
(
i
=
0
;
i
<
5
;
i
++
)
{
error
=
ili251x_switch_ic_mode
(
client
,
REG_SET_MODE_AP
);
if
(
!
error
)
break
;
}
if
(
error
)
goto
exit
;
dev_dbg
(
dev
,
"IC is now in Application mode
\n
"
);
error
=
ili251x_firmware_update_cached_state
(
dev
);
if
(
error
)
goto
exit
;
error
=
count
;
exit:
ili251x_hardware_reset
(
dev
);
dev_dbg
(
dev
,
"Firmware update ended, error=%i
\n
"
,
error
);
enable_irq
(
client
->
irq
);
kfree
(
fwbuf
);
return
error
;
}
static
DEVICE_ATTR
(
firmware_update
,
0200
,
NULL
,
ili210x_firmware_update_store
);
static
struct
attribute
*
ili210x_attributes
[]
=
{
&
dev_attr_calibrate
.
attr
,
&
dev_attr_firmware_update
.
attr
,
&
dev_attr_firmware_version
.
attr
,
&
dev_attr_kernel_version
.
attr
,
&
dev_attr_protocol_version
.
attr
,
&
dev_attr_mode
.
attr
,
NULL
,
};
static
umode_t
ili210x_
calibrate
_visible
(
struct
kobject
*
kobj
,
static
umode_t
ili210x_
attributes
_visible
(
struct
kobject
*
kobj
,
struct
attribute
*
attr
,
int
index
)
{
struct
device
*
dev
=
kobj_to_dev
(
kobj
);
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
ili210x
*
priv
=
i2c_get_clientdata
(
client
);
return
priv
->
chip
->
has_calibrate_reg
?
attr
->
mode
:
0
;
/* Calibrate is present on all ILI2xxx which have calibrate register */
if
(
attr
==
&
dev_attr_calibrate
.
attr
)
return
priv
->
chip
->
has_calibrate_reg
?
attr
->
mode
:
0
;
/* Firmware/Kernel/Protocol/BootMode is implememted only for ILI251x */
if
(
!
priv
->
chip
->
has_firmware_proto
)
return
0
;
return
attr
->
mode
;
}
static
const
struct
attribute_group
ili210x_attr_group
=
{
.
attrs
=
ili210x_attributes
,
.
is_visible
=
ili210x_
calibrate
_visible
,
.
is_visible
=
ili210x_
attributes
_visible
,
};
static
void
ili210x_power_down
(
void
*
data
)
...
...
@@ -449,6 +980,12 @@ static int ili210x_i2c_probe(struct i2c_client *client,
input_set_abs_params
(
input
,
ABS_MT_POSITION_Y
,
0
,
max_xy
,
0
,
0
);
if
(
priv
->
chip
->
has_pressure_reg
)
input_set_abs_params
(
input
,
ABS_MT_PRESSURE
,
0
,
0xa
,
0
,
0
);
error
=
ili251x_firmware_update_cached_state
(
dev
);
if
(
error
)
{
dev_err
(
dev
,
"Unable to cache firmware information, err: %d
\n
"
,
error
);
return
error
;
}
touchscreen_parse_properties
(
input
,
true
,
&
priv
->
prop
);
error
=
input_mt_init_slots
(
input
,
priv
->
chip
->
max_touches
,
...
...
drivers/input/touchscreen/raydium_i2c_ts.c
浏览文件 @
efe6f16c
...
...
@@ -37,6 +37,7 @@
#define RM_CMD_BOOT_READ 0x44
/* send wait bl data ready*/
#define RM_BOOT_RDY 0xFF
/* bl data ready */
#define RM_BOOT_CMD_READHWID 0x0E
/* read hwid */
/* I2C main commands */
#define RM_CMD_QUERY_BANK 0x2B
...
...
@@ -290,6 +291,44 @@ static int raydium_i2c_sw_reset(struct i2c_client *client)
return
0
;
}
static
int
raydium_i2c_query_ts_bootloader_info
(
struct
raydium_data
*
ts
)
{
struct
i2c_client
*
client
=
ts
->
client
;
static
const
u8
get_hwid
[]
=
{
RM_BOOT_CMD_READHWID
,
0x10
,
0xc0
,
0x01
,
0x00
,
0x04
,
0x00
};
u8
rbuf
[
5
]
=
{
0
};
u32
hw_ver
;
int
error
;
error
=
raydium_i2c_send
(
client
,
RM_CMD_BOOT_WRT
,
get_hwid
,
sizeof
(
get_hwid
));
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"WRT HWID command failed: %d
\n
"
,
error
);
return
error
;
}
error
=
raydium_i2c_send
(
client
,
RM_CMD_BOOT_ACK
,
rbuf
,
1
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"Ack HWID command failed: %d
\n
"
,
error
);
return
error
;
}
error
=
raydium_i2c_read
(
client
,
RM_CMD_BOOT_CHK
,
rbuf
,
sizeof
(
rbuf
));
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"Read HWID command failed: %d (%4ph)
\n
"
,
error
,
rbuf
+
1
);
hw_ver
=
0xffffffffUL
;
}
else
{
hw_ver
=
get_unaligned_be32
(
rbuf
+
1
);
}
ts
->
info
.
hw_ver
=
cpu_to_le32
(
hw_ver
);
ts
->
info
.
main_ver
=
0xff
;
ts
->
info
.
sub_ver
=
0xff
;
return
error
;
}
static
int
raydium_i2c_query_ts_info
(
struct
raydium_data
*
ts
)
{
struct
i2c_client
*
client
=
ts
->
client
;
...
...
@@ -388,13 +427,10 @@ static int raydium_i2c_initialize(struct raydium_data *ts)
if
(
error
)
ts
->
boot_mode
=
RAYDIUM_TS_BLDR
;
if
(
ts
->
boot_mode
==
RAYDIUM_TS_BLDR
)
{
ts
->
info
.
hw_ver
=
cpu_to_le32
(
0xffffffffUL
);
ts
->
info
.
main_ver
=
0xff
;
ts
->
info
.
sub_ver
=
0xff
;
}
else
{
if
(
ts
->
boot_mode
==
RAYDIUM_TS_BLDR
)
raydium_i2c_query_ts_bootloader_info
(
ts
);
else
raydium_i2c_query_ts_info
(
ts
);
}
return
error
;
}
...
...
@@ -1082,11 +1118,11 @@ static int raydium_i2c_probe(struct i2c_client *client,
if
(
error
)
return
error
;
error
=
devm_add_action
(
&
client
->
dev
,
raydium_i2c_power_off
,
ts
);
error
=
devm_add_action_or_reset
(
&
client
->
dev
,
raydium_i2c_power_off
,
ts
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"failed to install power off action: %d
\n
"
,
error
);
raydium_i2c_power_off
(
ts
);
return
error
;
}
...
...
@@ -1218,7 +1254,7 @@ static SIMPLE_DEV_PM_OPS(raydium_i2c_pm_ops,
raydium_i2c_suspend
,
raydium_i2c_resume
);
static
const
struct
i2c_device_id
raydium_i2c_id
[]
=
{
{
"raydium_i2c"
,
0
},
{
"raydium_i2c"
,
0
},
{
"rm32380"
,
0
},
{
/* sentinel */
}
};
...
...
drivers/input/touchscreen/st1232.c
浏览文件 @
efe6f16c
...
...
@@ -92,7 +92,7 @@ static int st1232_ts_wait_ready(struct st1232_ts_data *ts)
unsigned
int
retries
;
int
error
;
for
(
retries
=
10
;
retries
;
retries
--
)
{
for
(
retries
=
10
0
;
retries
;
retries
--
)
{
error
=
st1232_ts_read_data
(
ts
,
REG_STATUS
,
1
);
if
(
!
error
)
{
switch
(
ts
->
read_buf
[
0
])
{
...
...
@@ -389,6 +389,7 @@ static struct i2c_driver st1232_ts_driver = {
.
driver
=
{
.
name
=
ST1232_TS_NAME
,
.
of_match_table
=
st1232_ts_dt_ids
,
.
probe_type
=
PROBE_PREFER_ASYNCHRONOUS
,
.
pm
=
&
st1232_ts_pm_ops
,
},
};
...
...
drivers/input/touchscreen/tsc2004.c
浏览文件 @
efe6f16c
...
...
@@ -45,7 +45,9 @@ static int tsc2004_probe(struct i2c_client *i2c,
static
int
tsc2004_remove
(
struct
i2c_client
*
i2c
)
{
return
tsc200x_remove
(
&
i2c
->
dev
);
tsc200x_remove
(
&
i2c
->
dev
);
return
0
;
}
static
const
struct
i2c_device_id
tsc2004_idtable
[]
=
{
...
...
drivers/input/touchscreen/tsc2005.c
浏览文件 @
efe6f16c
...
...
@@ -66,7 +66,9 @@ static int tsc2005_probe(struct spi_device *spi)
static
int
tsc2005_remove
(
struct
spi_device
*
spi
)
{
return
tsc200x_remove
(
&
spi
->
dev
);
tsc200x_remove
(
&
spi
->
dev
);
return
0
;
}
#ifdef CONFIG_OF
...
...
drivers/input/touchscreen/tsc200x-core.c
浏览文件 @
efe6f16c
...
...
@@ -577,15 +577,13 @@ int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id,
}
EXPORT_SYMBOL_GPL
(
tsc200x_probe
);
int
tsc200x_remove
(
struct
device
*
dev
)
void
tsc200x_remove
(
struct
device
*
dev
)
{
struct
tsc200x
*
ts
=
dev_get_drvdata
(
dev
);
sysfs_remove_group
(
&
dev
->
kobj
,
&
tsc200x_attr_group
);
regulator_disable
(
ts
->
vio
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
tsc200x_remove
);
...
...
drivers/input/touchscreen/tsc200x-core.h
浏览文件 @
efe6f16c
...
...
@@ -74,6 +74,6 @@ extern const struct dev_pm_ops tsc200x_pm_ops;
int
tsc200x_probe
(
struct
device
*
dev
,
int
irq
,
const
struct
input_id
*
tsc_id
,
struct
regmap
*
regmap
,
int
(
*
tsc200x_cmd
)(
struct
device
*
dev
,
u8
cmd
));
int
tsc200x_remove
(
struct
device
*
dev
);
void
tsc200x_remove
(
struct
device
*
dev
);
#endif
drivers/input/touchscreen/wacom_i2c.c
浏览文件 @
efe6f16c
...
...
@@ -6,6 +6,7 @@
* <tobita.tatsunosuke@wacom.co.jp>
*/
#include <linux/bits.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/i2c.h>
...
...
@@ -14,6 +15,15 @@
#include <linux/interrupt.h>
#include <asm/unaligned.h>
/* Bitmasks (for data[3]) */
#define WACOM_TIP_SWITCH BIT(0)
#define WACOM_BARREL_SWITCH BIT(1)
#define WACOM_ERASER BIT(2)
#define WACOM_INVERT BIT(3)
#define WACOM_BARREL_SWITCH_2 BIT(4)
#define WACOM_IN_PROXIMITY BIT(5)
/* Registers */
#define WACOM_CMD_QUERY0 0x04
#define WACOM_CMD_QUERY1 0x00
#define WACOM_CMD_QUERY2 0x33
...
...
@@ -99,19 +109,19 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
if
(
error
<
0
)
goto
out
;
tsw
=
data
[
3
]
&
0x01
;
ers
=
data
[
3
]
&
0x04
;
f1
=
data
[
3
]
&
0x02
;
f2
=
data
[
3
]
&
0x10
;
tsw
=
data
[
3
]
&
WACOM_TIP_SWITCH
;
ers
=
data
[
3
]
&
WACOM_ERASER
;
f1
=
data
[
3
]
&
WACOM_BARREL_SWITCH
;
f2
=
data
[
3
]
&
WACOM_BARREL_SWITCH_2
;
x
=
le16_to_cpup
((
__le16
*
)
&
data
[
4
]);
y
=
le16_to_cpup
((
__le16
*
)
&
data
[
6
]);
pressure
=
le16_to_cpup
((
__le16
*
)
&
data
[
8
]);
if
(
!
wac_i2c
->
prox
)
wac_i2c
->
tool
=
(
data
[
3
]
&
0x0c
)
?
wac_i2c
->
tool
=
(
data
[
3
]
&
(
WACOM_ERASER
|
WACOM_INVERT
)
)
?
BTN_TOOL_RUBBER
:
BTN_TOOL_PEN
;
wac_i2c
->
prox
=
data
[
3
]
&
0x20
;
wac_i2c
->
prox
=
data
[
3
]
&
WACOM_IN_PROXIMITY
;
input_report_key
(
input
,
BTN_TOUCH
,
tsw
||
ers
);
input_report_key
(
input
,
wac_i2c
->
tool
,
wac_i2c
->
prox
);
...
...
include/linux/input/cy8ctmg110_pdata.h
已删除
100644 → 0
浏览文件 @
a02dcde5
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_CY8CTMG110_PDATA_H
#define _LINUX_CY8CTMG110_PDATA_H
struct
cy8ctmg110_pdata
{
int
reset_pin
;
/* Reset pin is wired to this GPIO (optional) */
};
#endif
include/linux/spi/ads7846.h
浏览文件 @
efe6f16c
/* SPDX-License-Identifier: GPL-2.0 */
/* linux/spi/ads7846.h */
/* Touchscreen characteristics vary between boards and models. The
* platform_data for the device's "struct device" holds this information.
*
* It's OK if the min/max values are zero.
*/
enum
ads7846_filter
{
ADS7846_FILTER_OK
,
ADS7846_FILTER_REPEAT
,
ADS7846_FILTER_IGNORE
,
};
struct
ads7846_platform_data
{
u16
model
;
/* 7843, 7845, 7846, 7873. */
u16
vref_delay_usecs
;
/* 0 for external vref; etc */
...
...
@@ -51,10 +40,6 @@ struct ads7846_platform_data {
int
gpio_pendown_debounce
;
/* platform specific debounce time for
* the gpio_pendown */
int
(
*
get_pendown_state
)(
void
);
int
(
*
filter_init
)
(
const
struct
ads7846_platform_data
*
pdata
,
void
**
filter_data
);
int
(
*
filter
)
(
void
*
filter_data
,
int
data_idx
,
int
*
val
);
void
(
*
filter_cleanup
)(
void
*
filter_data
);
void
(
*
wait_for_sync
)(
void
);
bool
wakeup
;
unsigned
long
irq_flags
;
...
...
kernel/reboot.c
浏览文件 @
efe6f16c
...
...
@@ -32,6 +32,7 @@ EXPORT_SYMBOL(cad_pid);
#define DEFAULT_REBOOT_MODE
#endif
enum
reboot_mode
reboot_mode
DEFAULT_REBOOT_MODE
;
EXPORT_SYMBOL_GPL
(
reboot_mode
);
enum
reboot_mode
panic_reboot_mode
=
REBOOT_UNDEFINED
;
/*
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录