Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
efe6f16c
Commit
efe6f16c
authored
Nov 11, 2021
by
Dmitry Torokhov
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'next' into for-linus
Prepare input updates for 5.16 merge window.
parents
a02dcde5
744d0090
Changes
45
Hide whitespace changes
Inline
Side-by-side
Showing
45 changed files
with
1833 additions
and
460 deletions
+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
No files found.
Documentation/devicetree/bindings/input/cap11xx.txt
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
efe6f16c
/*
*
/*
* MAX8925 ONKEY driver
*
* Copyright (C) 2009 Marvell International Ltd.
...
...
drivers/input/misc/palmas-pwrbutton.c
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
deleted
100644 → 0
View file @
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
View file @
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
View file @
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
;
/*
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment