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
nexedi
linux
Commits
cd510679
Commit
cd510679
authored
Apr 06, 2020
by
Dmitry Torokhov
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'next' into for-linus
Prepare input updates for 5.7 merge window.
parents
4134252a
3a857962
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
651 additions
and
210 deletions
+651
-210
Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt
...tion/devicetree/bindings/input/touchscreen/edt-ft5x06.txt
+0
-77
Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
...ion/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
+125
-0
Documentation/devicetree/bindings/input/touchscreen/goodix.yaml
...ntation/devicetree/bindings/input/touchscreen/goodix.yaml
+2
-0
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/i8042-x86ia64io.h
+11
-0
drivers/input/touchscreen/elants_i2c.c
drivers/input/touchscreen/elants_i2c.c
+1
-0
drivers/input/touchscreen/goodix.c
drivers/input/touchscreen/goodix.c
+494
-114
drivers/input/touchscreen/of_touchscreen.c
drivers/input/touchscreen/of_touchscreen.c
+17
-18
include/uapi/linux/input-event-codes.h
include/uapi/linux/input-event-codes.h
+1
-1
No files found.
Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt
deleted
100644 → 0
View file @
4134252a
FocalTech EDT-FT5x06 Polytouch driver
=====================================
There are 5 variants of the chip for various touch panel sizes
FT5206GE1 2.8" .. 3.8"
FT5306DE4 4.3" .. 7"
FT5406EE8 7" .. 8.9"
FT5506EEG 7" .. 8.9"
FT5726NEI 5.7” .. 11.6"
The software interface is identical for all those chips, so that
currently there is no need for the driver to distinguish between the
different chips. Nevertheless distinct compatible strings are used so
that a distinction can be added if necessary without changing the DT
bindings.
Required properties:
- compatible: "edt,edt-ft5206"
or: "edt,edt-ft5306"
or: "edt,edt-ft5406"
or: "edt,edt-ft5506"
or: "evervision,ev-ft5726"
or: "focaltech,ft6236"
- reg: I2C slave address of the chip (0x38)
- interrupts: interrupt specification for the touchdetect
interrupt
Optional properties:
- reset-gpios: GPIO specification for the RESET input
- wake-gpios: GPIO specification for the WAKE input
- vcc-supply: Regulator that supplies the touchscreen
- pinctrl-names: should be "default"
- pinctrl-0: a phandle pointing to the pin settings for the
control gpios
- wakeup-source: If present the device will act as wakeup-source
- threshold: allows setting the "click"-threshold in the range
from 0 to 80.
- gain: allows setting the sensitivity in the range from 0 to
31. Note that lower values indicate higher
sensitivity.
- offset: allows setting the edge compensation in the range from
0 to 31.
- offset-x: Same as offset, but applies only to the horizontal position.
Range from 0 to 80, only supported by evervision,ev-ft5726
devices.
- offset-y: Same as offset, but applies only to the vertical position.
Range from 0 to 80, only supported by evervision,ev-ft5726
devices.
- touchscreen-size-x : See touchscreen.txt
- touchscreen-size-y : See touchscreen.txt
- touchscreen-fuzz-x : See touchscreen.txt
- touchscreen-fuzz-y : See touchscreen.txt
- touchscreen-inverted-x : See touchscreen.txt
- touchscreen-inverted-y : See touchscreen.txt
- touchscreen-swapped-x-y : See touchscreen.txt
Example:
polytouch: edt-ft5x06@38 {
compatible = "edt,edt-ft5406", "edt,edt-ft5x06";
reg = <0x38>;
pinctrl-names = "default";
pinctrl-0 = <&edt_ft5x06_pins>;
interrupt-parent = <&gpio2>;
interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&gpio2 6 GPIO_ACTIVE_LOW>;
wake-gpios = <&gpio4 9 GPIO_ACTIVE_HIGH>;
};
Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
0 → 100644
View file @
cd510679
# SPDX-License-Identifier: GPL-2.0
%YAML
1.2
---
$id
:
http://devicetree.org/schemas/input/touchscreen/edt-ft5x06.yaml#
$schema
:
http://devicetree.org/meta-schemas/core.yaml#
title
:
FocalTech EDT-FT5x06 Polytouch Bindings
description
:
|
There are 5 variants of the chip for various touch panel sizes
FT5206GE1 2.8" .. 3.8"
FT5306DE4 4.3" .. 7"
FT5406EE8 7" .. 8.9"
FT5506EEG 7" .. 8.9"
FT5726NEI 5.7” .. 11.6"
maintainers
:
-
Dmitry Torokhov <dmitry.torokhov@gmail.com>
allOf
:
-
$ref
:
touchscreen.yaml#
-
if
:
properties
:
compatible
:
contains
:
enum
:
-
evervision,ev-ft5726
then
:
properties
:
offset-x
:
true
offset-y
:
true
properties
:
compatible
:
enum
:
-
edt,edt-ft5206
-
edt,edt-ft5306
-
edt,edt-ft5406
-
edt,edt-ft5506
-
evervision,ev-ft5726
-
focaltech,ft6236
reg
:
const
:
0x38
interrupts
:
maxItems
:
1
reset-gpios
:
maxItems
:
1
wake-gpios
:
maxItems
:
1
wakeup-source
:
true
vcc-supply
:
maxItems
:
1
gain
:
description
:
Allows setting the sensitivity in the range from 0 to 31.
Note that lower values indicate higher sensitivity.
allOf
:
-
$ref
:
/schemas/types.yaml#/definitions/uint32
-
minimum
:
0
-
maximum
:
31
offset
:
description
:
Allows setting the edge compensation in the range from 0 to 31.
allOf
:
-
$ref
:
/schemas/types.yaml#/definitions/uint32
-
minimum
:
0
-
maximum
:
31
offset-x
:
description
:
Same as offset, but applies only to the horizontal position.
Range from 0 to 80, only supported by evervision,ev-ft5726 devices.
allOf
:
-
$ref
:
/schemas/types.yaml#/definitions/uint32
-
minimum
:
0
-
maximum
:
80
offset-y
:
description
:
Same as offset, but applies only to the vertical position.
Range from 0 to 80, only supported by evervision,ev-ft5726 devices.
allOf
:
-
$ref
:
/schemas/types.yaml#/definitions/uint32
-
minimum
:
0
-
maximum
:
80
touchscreen-size-x
:
true
touchscreen-size-y
:
true
touchscreen-fuzz-x
:
true
touchscreen-fuzz-y
:
true
touchscreen-inverted-x
:
true
touchscreen-inverted-y
:
true
touchscreen-swapped-x-y
:
true
interrupt-controller
:
true
additionalProperties
:
false
required
:
-
compatible
-
reg
-
interrupts
examples
:
-
|
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
i2c@00000000 {
#address-cells = <1>;
#size-cells = <0>;
edt-ft5x06@38 {
compatible = "edt,edt-ft5406";
reg = <0x38>;
interrupt-parent = <&gpio2>;
interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&gpio2 6 GPIO_ACTIVE_LOW>;
wake-gpios = <&gpio4 9 GPIO_ACTIVE_HIGH>;
};
};
...
Documentation/devicetree/bindings/input/touchscreen/goodix.yaml
View file @
cd510679
...
...
@@ -21,6 +21,8 @@ properties:
-
goodix,gt911
-
goodix,gt9110
-
goodix,gt912
-
goodix,gt9147
-
goodix,gt917s
-
goodix,gt927
-
goodix,gt9271
-
goodix,gt928
...
...
drivers/input/serio/i8042-x86ia64io.h
View file @
cd510679
...
...
@@ -530,6 +530,17 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
DMI_MATCH
(
DMI_PRODUCT_VERSION
,
"Lenovo LaVie Z"
),
},
},
{
/*
* Acer Aspire 5738z
* Touchpad stops working in mux mode when dis- + re-enabled
* with the touchpad enable/disable toggle hotkey
*/
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Acer"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"Aspire 5738"
),
},
},
{
}
};
...
...
drivers/input/touchscreen/elants_i2c.c
View file @
cd510679
...
...
@@ -1309,6 +1309,7 @@ static int elants_i2c_probe(struct i2c_client *client,
input_set_abs_params
(
ts
->
input
,
ABS_MT_PRESSURE
,
0
,
255
,
0
,
0
);
input_abs_set_res
(
ts
->
input
,
ABS_MT_POSITION_X
,
ts
->
x_res
);
input_abs_set_res
(
ts
->
input
,
ABS_MT_POSITION_Y
,
ts
->
y_res
);
input_abs_set_res
(
ts
->
input
,
ABS_MT_TOUCH_MAJOR
,
1
);
error
=
input_register_device
(
ts
->
input
);
if
(
error
)
{
...
...
drivers/input/touchscreen/goodix.c
View file @
cd510679
...
...
@@ -29,33 +29,6 @@
#include <linux/of.h>
#include <asm/unaligned.h>
struct
goodix_ts_data
;
struct
goodix_chip_data
{
u16
config_addr
;
int
config_len
;
int
(
*
check_config
)(
struct
goodix_ts_data
*
,
const
struct
firmware
*
);
};
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
;
u16
id
;
u16
version
;
const
char
*
cfg_name
;
struct
completion
firmware_loading_complete
;
unsigned
long
irq_flags
;
unsigned
int
contact_size
;
};
#define GOODIX_GPIO_INT_NAME "irq"
#define GOODIX_GPIO_RST_NAME "reset"
...
...
@@ -65,10 +38,13 @@ struct goodix_ts_data {
#define GOODIX_CONTACT_SIZE 8
#define GOODIX_MAX_CONTACT_SIZE 9
#define GOODIX_MAX_CONTACTS 10
#define GOODIX_MAX_KEYS 7
#define GOODIX_CONFIG_M
AX_LENGTH 240
#define GOODIX_CONFIG_M
IN_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
...
...
@@ -80,39 +56,118 @@ struct goodix_ts_data {
#define GOODIX_REG_ID 0x8140
#define GOODIX_BUFFER_STATUS_READY BIT(7)
#define GOODIX_HAVE_KEY BIT(4)
#define GOODIX_BUFFER_STATUS_TIMEOUT 20
#define RESOLUTION_LOC 1
#define MAX_CONTACTS_LOC 5
#define TRIGGER_LOC 6
/* Our special handling for GPIO accesses through ACPI is x86 specific */
#if defined CONFIG_X86 && defined CONFIG_ACPI
#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
struct
firmware
*
cfg
);
const
u8
*
cfg
,
int
len
);
static
int
goodix_check_cfg_16
(
struct
goodix_ts_data
*
ts
,
const
struct
firmware
*
cfg
);
const
u8
*
cfg
,
int
len
);
static
void
goodix_calc_cfg_checksum_8
(
struct
goodix_ts_data
*
ts
);
static
void
goodix_calc_cfg_checksum_16
(
struct
goodix_ts_data
*
ts
);
static
const
struct
goodix_chip_data
gt1x_chip_data
=
{
.
config_addr
=
GOODIX_GT1X_REG_CONFIG_DATA
,
.
config_len
=
GOODIX_CONFIG_
MA
X_LENGTH
,
.
config_len
=
GOODIX_CONFIG_
GT9
X_LENGTH
,
.
check_config
=
goodix_check_cfg_16
,
.
calc_config_checksum
=
goodix_calc_cfg_checksum_16
,
};
static
const
struct
goodix_chip_data
gt911_chip_data
=
{
.
config_addr
=
GOODIX_GT9X_REG_CONFIG_DATA
,
.
config_len
=
GOODIX_CONFIG_911_LENGTH
,
.
check_config
=
goodix_check_cfg_8
,
.
calc_config_checksum
=
goodix_calc_cfg_checksum_8
,
};
static
const
struct
goodix_chip_data
gt967_chip_data
=
{
.
config_addr
=
GOODIX_GT9X_REG_CONFIG_DATA
,
.
config_len
=
GOODIX_CONFIG_967_LENGTH
,
.
check_config
=
goodix_check_cfg_8
,
.
calc_config_checksum
=
goodix_calc_cfg_checksum_8
,
};
static
const
struct
goodix_chip_data
gt9x_chip_data
=
{
.
config_addr
=
GOODIX_GT9X_REG_CONFIG_DATA
,
.
config_len
=
GOODIX_CONFIG_
MA
X_LENGTH
,
.
config_len
=
GOODIX_CONFIG_
GT9
X_LENGTH
,
.
check_config
=
goodix_check_cfg_8
,
.
calc_config_checksum
=
goodix_calc_cfg_checksum_8
,
};
static
const
struct
goodix_chip_id
goodix_chip_ids
[]
=
{
{
.
id
=
"1151"
,
.
data
=
&
gt1x_chip_data
},
{
.
id
=
"5663"
,
.
data
=
&
gt1x_chip_data
},
{
.
id
=
"5688"
,
.
data
=
&
gt1x_chip_data
},
{
.
id
=
"917S"
,
.
data
=
&
gt1x_chip_data
},
{
.
id
=
"911"
,
.
data
=
&
gt911_chip_data
},
{
.
id
=
"9271"
,
.
data
=
&
gt911_chip_data
},
{
.
id
=
"9110"
,
.
data
=
&
gt911_chip_data
},
{
.
id
=
"927"
,
.
data
=
&
gt911_chip_data
},
{
.
id
=
"928"
,
.
data
=
&
gt911_chip_data
},
{
.
id
=
"912"
,
.
data
=
&
gt967_chip_data
},
{
.
id
=
"9147"
,
.
data
=
&
gt967_chip_data
},
{
.
id
=
"967"
,
.
data
=
&
gt967_chip_data
},
{
}
};
static
const
unsigned
long
goodix_irq_flags
[]
=
{
...
...
@@ -168,6 +223,22 @@ static const struct dmi_system_id nine_bytes_report[] = {
{}
};
/*
* Those tablets have their x coordinate inverted
*/
static
const
struct
dmi_system_id
inverted_x_screen
[]
=
{
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
{
.
ident
=
"Cube I15-TC"
,
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Cube"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"I15-TC"
)
},
},
#endif
{}
};
/**
* goodix_i2c_read - read data from a register of the i2c slave device.
*
...
...
@@ -235,28 +306,16 @@ static int goodix_i2c_write_u8(struct i2c_client *client, u16 reg, u8 value)
return
goodix_i2c_write
(
client
,
reg
,
&
value
,
sizeof
(
value
));
}
static
const
struct
goodix_chip_data
*
goodix_get_chip_data
(
u16
id
)
static
const
struct
goodix_chip_data
*
goodix_get_chip_data
(
const
char
*
id
)
{
switch
(
id
)
{
case
1151
:
case
5663
:
case
5688
:
return
&
gt1x_chip_data
;
case
911
:
case
9271
:
case
9110
:
case
927
:
case
928
:
return
&
gt911_chip_data
;
case
912
:
case
967
:
return
&
gt967_chip_data
;
unsigned
int
i
;
default:
return
&
gt9x_chip_data
;
for
(
i
=
0
;
goodix_chip_ids
[
i
].
id
;
i
++
)
{
if
(
!
strcmp
(
goodix_chip_ids
[
i
].
id
,
id
))
return
goodix_chip_ids
[
i
].
data
;
}
return
&
gt9x_chip_data
;
}
static
int
goodix_ts_read_input_report
(
struct
goodix_ts_data
*
ts
,
u8
*
data
)
...
...
@@ -264,6 +323,13 @@ static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data)
unsigned
long
max_timeout
;
int
touch_num
;
int
error
;
u16
addr
=
GOODIX_READ_COOR_ADDR
;
/*
* We are going to read 1-byte header,
* ts->contact_size * max(1, touch_num) bytes of coordinates
* and 1-byte footer which contains the touch-key code.
*/
const
int
header_contact_keycode_size
=
1
+
ts
->
contact_size
+
1
;
/*
* The 'buffer status' bit, which indicates that the data is valid, is
...
...
@@ -272,8 +338,8 @@ static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data)
*/
max_timeout
=
jiffies
+
msecs_to_jiffies
(
GOODIX_BUFFER_STATUS_TIMEOUT
);
do
{
error
=
goodix_i2c_read
(
ts
->
client
,
GOODIX_READ_COOR_ADDR
,
data
,
ts
->
contact_size
+
1
);
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
);
...
...
@@ -286,11 +352,10 @@ static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data)
return
-
EPROTO
;
if
(
touch_num
>
1
)
{
data
+=
1
+
ts
->
contact_size
;
addr
+=
header_contact_keycode_size
;
data
+=
header_contact_keycode_size
;
error
=
goodix_i2c_read
(
ts
->
client
,
GOODIX_READ_COOR_ADDR
+
1
+
ts
->
contact_size
,
data
,
addr
,
data
,
ts
->
contact_size
*
(
touch_num
-
1
));
if
(
error
)
...
...
@@ -307,7 +372,7 @@ static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data)
* The Goodix panel will send spurious interrupts after a
* 'finger up' event, which will always cause a timeout.
*/
return
0
;
return
-
ENOMSG
;
}
static
void
goodix_ts_report_touch_8b
(
struct
goodix_ts_data
*
ts
,
u8
*
coor_data
)
...
...
@@ -340,6 +405,25 @@ static void goodix_ts_report_touch_9b(struct goodix_ts_data *ts, u8 *coor_data)
input_report_abs
(
ts
->
input_dev
,
ABS_MT_WIDTH_MAJOR
,
input_w
);
}
static
void
goodix_ts_report_key
(
struct
goodix_ts_data
*
ts
,
u8
*
data
)
{
int
touch_num
;
u8
key_value
;
int
i
;
if
(
data
[
0
]
&
GOODIX_HAVE_KEY
)
{
touch_num
=
data
[
0
]
&
0x0f
;
key_value
=
data
[
1
+
ts
->
contact_size
*
touch_num
];
for
(
i
=
0
;
i
<
GOODIX_MAX_KEYS
;
i
++
)
if
(
key_value
&
BIT
(
i
))
input_report_key
(
ts
->
input_dev
,
ts
->
keymap
[
i
],
1
);
}
else
{
for
(
i
=
0
;
i
<
GOODIX_MAX_KEYS
;
i
++
)
input_report_key
(
ts
->
input_dev
,
ts
->
keymap
[
i
],
0
);
}
}
/**
* goodix_process_events - Process incoming events
*
...
...
@@ -350,7 +434,7 @@ static void goodix_ts_report_touch_9b(struct goodix_ts_data *ts, u8 *coor_data)
*/
static
void
goodix_process_events
(
struct
goodix_ts_data
*
ts
)
{
u8
point_data
[
1
+
GOODIX_MAX_CONTACT_SIZE
*
GOODIX_MAX_CONTACTS
];
u8
point_data
[
2
+
GOODIX_MAX_CONTACT_SIZE
*
GOODIX_MAX_CONTACTS
];
int
touch_num
;
int
i
;
...
...
@@ -358,11 +442,7 @@ static void goodix_process_events(struct goodix_ts_data *ts)
if
(
touch_num
<
0
)
return
;
/*
* Bit 4 of the first byte reports the status of the capacitive
* Windows/Home button.
*/
input_report_key
(
ts
->
input_dev
,
KEY_LEFTMETA
,
point_data
[
0
]
&
BIT
(
4
));
goodix_ts_report_key
(
ts
,
point_data
);
for
(
i
=
0
;
i
<
touch_num
;
i
++
)
if
(
ts
->
contact_size
==
9
)
...
...
@@ -406,22 +486,21 @@ static int goodix_request_irq(struct goodix_ts_data *ts)
ts
->
irq_flags
,
ts
->
client
->
name
,
ts
);
}
static
int
goodix_check_cfg_8
(
struct
goodix_ts_data
*
ts
,
const
struct
firmware
*
cfg
)
static
int
goodix_check_cfg_8
(
struct
goodix_ts_data
*
ts
,
const
u8
*
cfg
,
int
len
)
{
int
i
,
raw_cfg_len
=
cfg
->
size
-
2
;
int
i
,
raw_cfg_len
=
len
-
2
;
u8
check_sum
=
0
;
for
(
i
=
0
;
i
<
raw_cfg_len
;
i
++
)
check_sum
+=
cfg
->
data
[
i
];
check_sum
+=
cfg
[
i
];
check_sum
=
(
~
check_sum
)
+
1
;
if
(
check_sum
!=
cfg
->
data
[
raw_cfg_len
])
{
if
(
check_sum
!=
cfg
[
raw_cfg_len
])
{
dev_err
(
&
ts
->
client
->
dev
,
"The checksum of the config fw is not correct"
);
return
-
EINVAL
;
}
if
(
cfg
->
data
[
raw_cfg_len
+
1
]
!=
1
)
{
if
(
cfg
[
raw_cfg_len
+
1
]
!=
1
)
{
dev_err
(
&
ts
->
client
->
dev
,
"Config fw must have Config_Fresh register set"
);
return
-
EINVAL
;
...
...
@@ -430,22 +509,35 @@ static int goodix_check_cfg_8(struct goodix_ts_data *ts,
return
0
;
}
static
int
goodix_check_cfg_16
(
struct
goodix_ts_data
*
ts
,
const
struct
firmware
*
cfg
)
static
void
goodix_calc_cfg_checksum_8
(
struct
goodix_ts_data
*
ts
)
{
int
i
,
raw_cfg_len
=
ts
->
chip
->
config_len
-
2
;
u8
check_sum
=
0
;
for
(
i
=
0
;
i
<
raw_cfg_len
;
i
++
)
check_sum
+=
ts
->
config
[
i
];
check_sum
=
(
~
check_sum
)
+
1
;
ts
->
config
[
raw_cfg_len
]
=
check_sum
;
ts
->
config
[
raw_cfg_len
+
1
]
=
1
;
/* Set "config_fresh" bit */
}
static
int
goodix_check_cfg_16
(
struct
goodix_ts_data
*
ts
,
const
u8
*
cfg
,
int
len
)
{
int
i
,
raw_cfg_len
=
cfg
->
size
-
3
;
int
i
,
raw_cfg_len
=
len
-
3
;
u16
check_sum
=
0
;
for
(
i
=
0
;
i
<
raw_cfg_len
;
i
+=
2
)
check_sum
+=
get_unaligned_be16
(
&
cfg
->
data
[
i
]);
check_sum
+=
get_unaligned_be16
(
&
cfg
[
i
]);
check_sum
=
(
~
check_sum
)
+
1
;
if
(
check_sum
!=
get_unaligned_be16
(
&
cfg
->
data
[
raw_cfg_len
]))
{
if
(
check_sum
!=
get_unaligned_be16
(
&
cfg
[
raw_cfg_len
]))
{
dev_err
(
&
ts
->
client
->
dev
,
"The checksum of the config fw is not correct"
);
return
-
EINVAL
;
}
if
(
cfg
->
data
[
raw_cfg_len
+
2
]
!=
1
)
{
if
(
cfg
[
raw_cfg_len
+
2
]
!=
1
)
{
dev_err
(
&
ts
->
client
->
dev
,
"Config fw must have Config_Fresh register set"
);
return
-
EINVAL
;
...
...
@@ -454,22 +546,35 @@ static int goodix_check_cfg_16(struct goodix_ts_data *ts,
return
0
;
}
static
void
goodix_calc_cfg_checksum_16
(
struct
goodix_ts_data
*
ts
)
{
int
i
,
raw_cfg_len
=
ts
->
chip
->
config_len
-
3
;
u16
check_sum
=
0
;
for
(
i
=
0
;
i
<
raw_cfg_len
;
i
+=
2
)
check_sum
+=
get_unaligned_be16
(
&
ts
->
config
[
i
]);
check_sum
=
(
~
check_sum
)
+
1
;
put_unaligned_be16
(
check_sum
,
&
ts
->
config
[
raw_cfg_len
]);
ts
->
config
[
raw_cfg_len
+
2
]
=
1
;
/* Set "config_fresh" bit */
}
/**
* goodix_check_cfg - Checks if config fw is valid
*
* @ts: goodix_ts_data pointer
* @cfg: firmware config data
*/
static
int
goodix_check_cfg
(
struct
goodix_ts_data
*
ts
,
const
struct
firmware
*
cfg
)
static
int
goodix_check_cfg
(
struct
goodix_ts_data
*
ts
,
const
u8
*
cfg
,
int
len
)
{
if
(
cfg
->
size
>
GOODIX_CONFIG_MAX_LENGTH
)
{
if
(
len
<
GOODIX_CONFIG_MIN_LENGTH
||
len
>
GOODIX_CONFIG_MAX_LENGTH
)
{
dev_err
(
&
ts
->
client
->
dev
,
"The length of the config fw is not correct"
);
return
-
EINVAL
;
}
return
ts
->
chip
->
check_config
(
ts
,
cfg
);
return
ts
->
chip
->
check_config
(
ts
,
cfg
,
len
);
}
/**
...
...
@@ -478,17 +583,15 @@ static int goodix_check_cfg(struct goodix_ts_data *ts,
* @ts: goodix_ts_data pointer
* @cfg: config firmware to write to device
*/
static
int
goodix_send_cfg
(
struct
goodix_ts_data
*
ts
,
const
struct
firmware
*
cfg
)
static
int
goodix_send_cfg
(
struct
goodix_ts_data
*
ts
,
const
u8
*
cfg
,
int
len
)
{
int
error
;
error
=
goodix_check_cfg
(
ts
,
cfg
);
error
=
goodix_check_cfg
(
ts
,
cfg
,
len
);
if
(
error
)
return
error
;
error
=
goodix_i2c_write
(
ts
->
client
,
ts
->
chip
->
config_addr
,
cfg
->
data
,
cfg
->
size
);
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
);
...
...
@@ -502,17 +605,93 @@ static int goodix_send_cfg(struct goodix_ts_data *ts,
return
0
;
}
#ifdef ACPI_GPIO_SUPPORT
static
int
goodix_pin_acpi_direction_input
(
struct
goodix_ts_data
*
ts
)
{
acpi_handle
handle
=
ACPI_HANDLE
(
&
ts
->
client
->
dev
);
acpi_status
status
;
status
=
acpi_evaluate_object
(
handle
,
"INTI"
,
NULL
,
NULL
);
return
ACPI_SUCCESS
(
status
)
?
0
:
-
EIO
;
}
static
int
goodix_pin_acpi_output_method
(
struct
goodix_ts_data
*
ts
,
int
value
)
{
acpi_handle
handle
=
ACPI_HANDLE
(
&
ts
->
client
->
dev
);
acpi_status
status
;
status
=
acpi_execute_simple_method
(
handle
,
"INTO"
,
value
);
return
ACPI_SUCCESS
(
status
)
?
0
:
-
EIO
;
}
#else
static
int
goodix_pin_acpi_direction_input
(
struct
goodix_ts_data
*
ts
)
{
dev_err
(
&
ts
->
client
->
dev
,
"%s called on device without ACPI support
\n
"
,
__func__
);
return
-
EINVAL
;
}
static
int
goodix_pin_acpi_output_method
(
struct
goodix_ts_data
*
ts
,
int
value
)
{
dev_err
(
&
ts
->
client
->
dev
,
"%s called on device without ACPI support
\n
"
,
__func__
);
return
-
EINVAL
;
}
#endif
static
int
goodix_irq_direction_output
(
struct
goodix_ts_data
*
ts
,
int
value
)
{
switch
(
ts
->
irq_pin_access_method
)
{
case
IRQ_PIN_ACCESS_NONE
:
dev_err
(
&
ts
->
client
->
dev
,
"%s called without an irq_pin_access_method set
\n
"
,
__func__
);
return
-
EINVAL
;
case
IRQ_PIN_ACCESS_GPIO
:
return
gpiod_direction_output
(
ts
->
gpiod_int
,
value
);
case
IRQ_PIN_ACCESS_ACPI_GPIO
:
/*
* The IRQ pin triggers on a falling edge, so its gets marked
* as active-low, use output_raw to avoid the value inversion.
*/
return
gpiod_direction_output_raw
(
ts
->
gpiod_int
,
value
);
case
IRQ_PIN_ACCESS_ACPI_METHOD
:
return
goodix_pin_acpi_output_method
(
ts
,
value
);
}
return
-
EINVAL
;
/* Never reached */
}
static
int
goodix_irq_direction_input
(
struct
goodix_ts_data
*
ts
)
{
switch
(
ts
->
irq_pin_access_method
)
{
case
IRQ_PIN_ACCESS_NONE
:
dev_err
(
&
ts
->
client
->
dev
,
"%s called without an irq_pin_access_method set
\n
"
,
__func__
);
return
-
EINVAL
;
case
IRQ_PIN_ACCESS_GPIO
:
return
gpiod_direction_input
(
ts
->
gpiod_int
);
case
IRQ_PIN_ACCESS_ACPI_GPIO
:
return
gpiod_direction_input
(
ts
->
gpiod_int
);
case
IRQ_PIN_ACCESS_ACPI_METHOD
:
return
goodix_pin_acpi_direction_input
(
ts
);
}
return
-
EINVAL
;
/* Never reached */
}
static
int
goodix_int_sync
(
struct
goodix_ts_data
*
ts
)
{
int
error
;
error
=
g
piod_direction_output
(
ts
->
gpiod_int
,
0
);
error
=
g
oodix_irq_direction_output
(
ts
,
0
);
if
(
error
)
return
error
;
msleep
(
50
);
/* T5: 50ms */
error
=
g
piod_direction_input
(
ts
->
gpiod_int
);
error
=
g
oodix_irq_direction_input
(
ts
);
if
(
error
)
return
error
;
...
...
@@ -536,7 +715,7 @@ static int goodix_reset(struct goodix_ts_data *ts)
msleep
(
20
);
/* T2: > 10ms */
/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */
error
=
g
piod_direction_output
(
ts
->
gpiod_int
,
ts
->
client
->
addr
==
0x14
);
error
=
g
oodix_irq_direction_output
(
ts
,
ts
->
client
->
addr
==
0x14
);
if
(
error
)
return
error
;
...
...
@@ -560,6 +739,124 @@ static int goodix_reset(struct goodix_ts_data *ts)
return
0
;
}
#ifdef ACPI_GPIO_SUPPORT
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
static
const
struct
x86_cpu_id
baytrail_cpu_ids
[]
=
{
{
X86_VENDOR_INTEL
,
6
,
INTEL_FAM6_ATOM_SILVERMONT
,
X86_FEATURE_ANY
,
},
{}
};
static
inline
bool
is_byt
(
void
)
{
const
struct
x86_cpu_id
*
id
=
x86_match_cpu
(
baytrail_cpu_ids
);
return
!!
id
;
}
static
const
struct
acpi_gpio_params
first_gpio
=
{
0
,
0
,
false
};
static
const
struct
acpi_gpio_params
second_gpio
=
{
1
,
0
,
false
};
static
const
struct
acpi_gpio_mapping
acpi_goodix_int_first_gpios
[]
=
{
{
GOODIX_GPIO_INT_NAME
"-gpios"
,
&
first_gpio
,
1
},
{
GOODIX_GPIO_RST_NAME
"-gpios"
,
&
second_gpio
,
1
},
{
},
};
static
const
struct
acpi_gpio_mapping
acpi_goodix_int_last_gpios
[]
=
{
{
GOODIX_GPIO_RST_NAME
"-gpios"
,
&
first_gpio
,
1
},
{
GOODIX_GPIO_INT_NAME
"-gpios"
,
&
second_gpio
,
1
},
{
},
};
static
const
struct
acpi_gpio_mapping
acpi_goodix_reset_only_gpios
[]
=
{
{
GOODIX_GPIO_RST_NAME
"-gpios"
,
&
first_gpio
,
1
},
{
},
};
static
int
goodix_resource
(
struct
acpi_resource
*
ares
,
void
*
data
)
{
struct
goodix_ts_data
*
ts
=
data
;
struct
device
*
dev
=
&
ts
->
client
->
dev
;
struct
acpi_resource_gpio
*
gpio
;
switch
(
ares
->
type
)
{
case
ACPI_RESOURCE_TYPE_GPIO
:
gpio
=
&
ares
->
data
.
gpio
;
if
(
gpio
->
connection_type
==
ACPI_RESOURCE_GPIO_TYPE_INT
)
{
if
(
ts
->
gpio_int_idx
==
-
1
)
{
ts
->
gpio_int_idx
=
ts
->
gpio_count
;
}
else
{
dev_err
(
dev
,
"More then one GpioInt resource, ignoring ACPI GPIO resources
\n
"
);
ts
->
gpio_int_idx
=
-
2
;
}
}
ts
->
gpio_count
++
;
break
;
default:
break
;
}
return
0
;
}
/*
* This function gets called in case we fail to get the irq GPIO directly
* because the ACPI tables lack GPIO-name to APCI _CRS index mappings
* (no _DSD UUID daffd814-6eba-4d8c-8a91-bc9bbf4aa301 data).
* In that case we add our own mapping and then goodix_get_gpio_config()
* retries to get the GPIOs based on the added mapping.
*/
static
int
goodix_add_acpi_gpio_mappings
(
struct
goodix_ts_data
*
ts
)
{
const
struct
acpi_gpio_mapping
*
gpio_mapping
=
NULL
;
struct
device
*
dev
=
&
ts
->
client
->
dev
;
LIST_HEAD
(
resources
);
int
ret
;
ts
->
gpio_count
=
0
;
ts
->
gpio_int_idx
=
-
1
;
ret
=
acpi_dev_get_resources
(
ACPI_COMPANION
(
dev
),
&
resources
,
goodix_resource
,
ts
);
if
(
ret
<
0
)
{
dev_err
(
dev
,
"Error getting ACPI resources: %d
\n
"
,
ret
);
return
ret
;
}
acpi_dev_free_resource_list
(
&
resources
);
if
(
ts
->
gpio_count
==
2
&&
ts
->
gpio_int_idx
==
0
)
{
ts
->
irq_pin_access_method
=
IRQ_PIN_ACCESS_ACPI_GPIO
;
gpio_mapping
=
acpi_goodix_int_first_gpios
;
}
else
if
(
ts
->
gpio_count
==
2
&&
ts
->
gpio_int_idx
==
1
)
{
ts
->
irq_pin_access_method
=
IRQ_PIN_ACCESS_ACPI_GPIO
;
gpio_mapping
=
acpi_goodix_int_last_gpios
;
}
else
if
(
ts
->
gpio_count
==
1
&&
ts
->
gpio_int_idx
==
-
1
&&
acpi_has_method
(
ACPI_HANDLE
(
dev
),
"INTI"
)
&&
acpi_has_method
(
ACPI_HANDLE
(
dev
),
"INTO"
))
{
dev_info
(
dev
,
"Using ACPI INTI and INTO methods for IRQ pin access
\n
"
);
ts
->
irq_pin_access_method
=
IRQ_PIN_ACCESS_ACPI_METHOD
;
gpio_mapping
=
acpi_goodix_reset_only_gpios
;
}
else
if
(
is_byt
()
&&
ts
->
gpio_count
==
2
&&
ts
->
gpio_int_idx
==
-
1
)
{
dev_info
(
dev
,
"No ACPI GpioInt resource, assuming that the GPIO order is reset, int
\n
"
);
ts
->
irq_pin_access_method
=
IRQ_PIN_ACCESS_ACPI_GPIO
;
gpio_mapping
=
acpi_goodix_int_last_gpios
;
}
else
{
dev_warn
(
dev
,
"Unexpected ACPI resources: gpio_count %d, gpio_int_idx %d
\n
"
,
ts
->
gpio_count
,
ts
->
gpio_int_idx
);
return
-
EINVAL
;
}
return
devm_acpi_dev_add_driver_gpios
(
dev
,
gpio_mapping
);
}
#else
static
int
goodix_add_acpi_gpio_mappings
(
struct
goodix_ts_data
*
ts
)
{
return
-
EINVAL
;
}
#endif
/* CONFIG_X86 && CONFIG_ACPI */
/**
* goodix_get_gpio_config - Get GPIO config from ACPI/DT
*
...
...
@@ -570,6 +867,7 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
int
error
;
struct
device
*
dev
;
struct
gpio_desc
*
gpiod
;
bool
added_acpi_mappings
=
false
;
if
(
!
ts
->
client
)
return
-
EINVAL
;
...
...
@@ -593,6 +891,7 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
return
error
;
}
retry_get_irq_gpio:
/* Get the interrupt GPIO pin number */
gpiod
=
devm_gpiod_get_optional
(
dev
,
GOODIX_GPIO_INT_NAME
,
GPIOD_IN
);
if
(
IS_ERR
(
gpiod
))
{
...
...
@@ -602,6 +901,11 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
GOODIX_GPIO_INT_NAME
,
error
);
return
error
;
}
if
(
!
gpiod
&&
has_acpi_companion
(
dev
)
&&
!
added_acpi_mappings
)
{
added_acpi_mappings
=
true
;
if
(
goodix_add_acpi_gpio_mappings
(
ts
)
==
0
)
goto
retry_get_irq_gpio
;
}
ts
->
gpiod_int
=
gpiod
;
...
...
@@ -617,6 +921,31 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
ts
->
gpiod_rst
=
gpiod
;
switch
(
ts
->
irq_pin_access_method
)
{
case
IRQ_PIN_ACCESS_ACPI_GPIO
:
/*
* We end up here if goodix_add_acpi_gpio_mappings() has
* called devm_acpi_dev_add_driver_gpios() because the ACPI
* tables did not contain name to index mappings.
* Check that we successfully got both GPIOs after we've
* added our own acpi_gpio_mapping and if we did not get both
* GPIOs reset irq_pin_access_method to IRQ_PIN_ACCESS_NONE.
*/
if
(
!
ts
->
gpiod_int
||
!
ts
->
gpiod_rst
)
ts
->
irq_pin_access_method
=
IRQ_PIN_ACCESS_NONE
;
break
;
case
IRQ_PIN_ACCESS_ACPI_METHOD
:
if
(
!
ts
->
gpiod_rst
)
ts
->
irq_pin_access_method
=
IRQ_PIN_ACCESS_NONE
;
break
;
default:
if
(
ts
->
gpiod_int
&&
ts
->
gpiod_rst
)
{
ts
->
reset_controller_at_probe
=
true
;
ts
->
load_cfg_from_disk
=
true
;
ts
->
irq_pin_access_method
=
IRQ_PIN_ACCESS_GPIO
;
}
}
return
0
;
}
...
...
@@ -629,12 +958,11 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
*/
static
void
goodix_read_config
(
struct
goodix_ts_data
*
ts
)
{
u8
config
[
GOODIX_CONFIG_MAX_LENGTH
];
int
x_max
,
y_max
;
int
error
;
error
=
goodix_i2c_read
(
ts
->
client
,
ts
->
chip
->
config_addr
,
config
,
ts
->
chip
->
config_len
);
ts
->
config
,
ts
->
chip
->
config_len
);
if
(
error
)
{
dev_warn
(
&
ts
->
client
->
dev
,
"Error reading config: %d
\n
"
,
error
);
...
...
@@ -643,15 +971,17 @@ static void goodix_read_config(struct goodix_ts_data *ts)
return
;
}
ts
->
int_trigger_type
=
config
[
TRIGGER_LOC
]
&
0x03
;
ts
->
max_touch_num
=
config
[
MAX_CONTACTS_LOC
]
&
0x0f
;
ts
->
int_trigger_type
=
ts
->
config
[
TRIGGER_LOC
]
&
0x03
;
ts
->
max_touch_num
=
ts
->
config
[
MAX_CONTACTS_LOC
]
&
0x0f
;
x_max
=
get_unaligned_le16
(
&
config
[
RESOLUTION_LOC
]);
y_max
=
get_unaligned_le16
(
&
config
[
RESOLUTION_LOC
+
2
]);
x_max
=
get_unaligned_le16
(
&
ts
->
config
[
RESOLUTION_LOC
]);
y_max
=
get_unaligned_le16
(
&
ts
->
config
[
RESOLUTION_LOC
+
2
]);
if
(
x_max
&&
y_max
)
{
input_abs_set_max
(
ts
->
input_dev
,
ABS_MT_POSITION_X
,
x_max
-
1
);
input_abs_set_max
(
ts
->
input_dev
,
ABS_MT_POSITION_Y
,
y_max
-
1
);
}
ts
->
chip
->
calc_config_checksum
(
ts
);
}
/**
...
...
@@ -663,7 +993,7 @@ static int goodix_read_version(struct goodix_ts_data *ts)
{
int
error
;
u8
buf
[
6
];
char
id_str
[
5
];
char
id_str
[
GOODIX_ID_MAX_LEN
+
1
];
error
=
goodix_i2c_read
(
ts
->
client
,
GOODIX_REG_ID
,
buf
,
sizeof
(
buf
));
if
(
error
)
{
...
...
@@ -671,14 +1001,13 @@ static int goodix_read_version(struct goodix_ts_data *ts)
return
error
;
}
memcpy
(
id_str
,
buf
,
4
);
id_str
[
4
]
=
0
;
if
(
kstrtou16
(
id_str
,
10
,
&
ts
->
id
))
ts
->
id
=
0x1001
;
memcpy
(
id_str
,
buf
,
GOODIX_ID_MAX_LEN
);
id_str
[
GOODIX_ID_MAX_LEN
]
=
0
;
strscpy
(
ts
->
id
,
id_str
,
GOODIX_ID_MAX_LEN
+
1
);
ts
->
version
=
get_unaligned_le16
(
&
buf
[
4
]);
dev_info
(
&
ts
->
client
->
dev
,
"ID %
d
, version: %04x
\n
"
,
ts
->
id
,
dev_info
(
&
ts
->
client
->
dev
,
"ID %
s
, version: %04x
\n
"
,
ts
->
id
,
ts
->
version
);
return
0
;
...
...
@@ -722,6 +1051,7 @@ static int goodix_i2c_test(struct i2c_client *client)
static
int
goodix_configure_dev
(
struct
goodix_ts_data
*
ts
)
{
int
error
;
int
i
;
ts
->
int_trigger_type
=
GOODIX_INT_TRIGGER
;
ts
->
max_touch_num
=
GOODIX_MAX_CONTACTS
;
...
...
@@ -736,11 +1066,23 @@ static int goodix_configure_dev(struct goodix_ts_data *ts)
ts
->
input_dev
->
phys
=
"input/ts"
;
ts
->
input_dev
->
id
.
bustype
=
BUS_I2C
;
ts
->
input_dev
->
id
.
vendor
=
0x0416
;
ts
->
input_dev
->
id
.
product
=
ts
->
id
;
if
(
kstrtou16
(
ts
->
id
,
10
,
&
ts
->
input_dev
->
id
.
product
))
ts
->
input_dev
->
id
.
product
=
0x1001
;
ts
->
input_dev
->
id
.
version
=
ts
->
version
;
ts
->
input_dev
->
keycode
=
ts
->
keymap
;
ts
->
input_dev
->
keycodesize
=
sizeof
(
ts
->
keymap
[
0
]);
ts
->
input_dev
->
keycodemax
=
GOODIX_MAX_KEYS
;
/* Capacitive Windows/Home button on some devices */
input_set_capability
(
ts
->
input_dev
,
EV_KEY
,
KEY_LEFTMETA
);
for
(
i
=
0
;
i
<
GOODIX_MAX_KEYS
;
++
i
)
{
if
(
i
==
0
)
ts
->
keymap
[
i
]
=
KEY_LEFTMETA
;
else
ts
->
keymap
[
i
]
=
KEY_F1
+
(
i
-
1
);
input_set_capability
(
ts
->
input_dev
,
EV_KEY
,
ts
->
keymap
[
i
]);
}
input_set_capability
(
ts
->
input_dev
,
EV_ABS
,
ABS_MT_POSITION_X
);
input_set_capability
(
ts
->
input_dev
,
EV_ABS
,
ABS_MT_POSITION_Y
);
...
...
@@ -780,6 +1122,12 @@ static int goodix_configure_dev(struct goodix_ts_data *ts)
"Non-standard 9-bytes report format quirk
\n
"
);
}
if
(
dmi_check_system
(
inverted_x_screen
))
{
ts
->
prop
.
invert_x
=
true
;
dev_dbg
(
&
ts
->
client
->
dev
,
"Applying 'inverted x screen' quirk
\n
"
);
}
error
=
input_mt_init_slots
(
ts
->
input_dev
,
ts
->
max_touch_num
,
INPUT_MT_DIRECT
|
INPUT_MT_DROP_UNUSED
);
if
(
error
)
{
...
...
@@ -820,7 +1168,7 @@ static void goodix_config_cb(const struct firmware *cfg, void *ctx)
if
(
cfg
)
{
/* send device configuration to the firmware */
error
=
goodix_send_cfg
(
ts
,
cfg
);
error
=
goodix_send_cfg
(
ts
,
cfg
->
data
,
cfg
->
size
);
if
(
error
)
goto
err_release_cfg
;
}
...
...
@@ -889,7 +1237,8 @@ static int goodix_ts_probe(struct i2c_client *client,
if
(
error
)
return
error
;
if
(
ts
->
gpiod_int
&&
ts
->
gpiod_rst
)
{
reset:
if
(
ts
->
reset_controller_at_probe
)
{
/* reset the controller */
error
=
goodix_reset
(
ts
);
if
(
error
)
{
...
...
@@ -900,6 +1249,12 @@ static int goodix_ts_probe(struct i2c_client *client,
error
=
goodix_i2c_test
(
client
);
if
(
error
)
{
if
(
!
ts
->
reset_controller_at_probe
&&
ts
->
irq_pin_access_method
!=
IRQ_PIN_ACCESS_NONE
)
{
/* Retry after a controller reset */
ts
->
reset_controller_at_probe
=
true
;
goto
reset
;
}
dev_err
(
&
client
->
dev
,
"I2C communication failure: %d
\n
"
,
error
);
return
error
;
}
...
...
@@ -912,10 +1267,10 @@ static int goodix_ts_probe(struct i2c_client *client,
ts
->
chip
=
goodix_get_chip_data
(
ts
->
id
);
if
(
ts
->
gpiod_int
&&
ts
->
gpiod_rst
)
{
if
(
ts
->
load_cfg_from_disk
)
{
/* update device config */
ts
->
cfg_name
=
devm_kasprintf
(
&
client
->
dev
,
GFP_KERNEL
,
"goodix_%
d
_cfg.bin"
,
ts
->
id
);
"goodix_%
s
_cfg.bin"
,
ts
->
id
);
if
(
!
ts
->
cfg_name
)
return
-
ENOMEM
;
...
...
@@ -943,7 +1298,7 @@ static int goodix_ts_remove(struct i2c_client *client)
{
struct
goodix_ts_data
*
ts
=
i2c_get_clientdata
(
client
);
if
(
ts
->
gpiod_int
&&
ts
->
gpiod_rst
)
if
(
ts
->
load_cfg_from_disk
)
wait_for_completion
(
&
ts
->
firmware_loading_complete
);
return
0
;
...
...
@@ -955,19 +1310,20 @@ static int __maybe_unused goodix_suspend(struct device *dev)
struct
goodix_ts_data
*
ts
=
i2c_get_clientdata
(
client
);
int
error
;
if
(
ts
->
load_cfg_from_disk
)
wait_for_completion
(
&
ts
->
firmware_loading_complete
);
/* We need gpio pins to suspend/resume */
if
(
!
ts
->
gpiod_int
||
!
ts
->
gpiod_rst
)
{
if
(
ts
->
irq_pin_access_method
==
IRQ_PIN_ACCESS_NONE
)
{
disable_irq
(
client
->
irq
);
return
0
;
}
wait_for_completion
(
&
ts
->
firmware_loading_complete
);
/* Free IRQ as IRQ pin is used as output in the suspend sequence */
goodix_free_irq
(
ts
);
/* Output LOW on the INT pin for 5 ms */
error
=
g
piod_direction_output
(
ts
->
gpiod_int
,
0
);
error
=
g
oodix_irq_direction_output
(
ts
,
0
);
if
(
error
)
{
goodix_request_irq
(
ts
);
return
error
;
...
...
@@ -979,7 +1335,7 @@ static int __maybe_unused goodix_suspend(struct device *dev)
GOODIX_CMD_SCREEN_OFF
);
if
(
error
)
{
dev_err
(
&
ts
->
client
->
dev
,
"Screen off command failed
\n
"
);
g
piod_direction_input
(
ts
->
gpiod_int
);
g
oodix_irq_direction_input
(
ts
);
goodix_request_irq
(
ts
);
return
-
EAGAIN
;
}
...
...
@@ -997,9 +1353,10 @@ static int __maybe_unused goodix_resume(struct device *dev)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
goodix_ts_data
*
ts
=
i2c_get_clientdata
(
client
);
u8
config_ver
;
int
error
;
if
(
!
ts
->
gpiod_int
||
!
ts
->
gpiod_rst
)
{
if
(
ts
->
irq_pin_access_method
==
IRQ_PIN_ACCESS_NONE
)
{
enable_irq
(
client
->
irq
);
return
0
;
}
...
...
@@ -1008,7 +1365,7 @@ static int __maybe_unused goodix_resume(struct device *dev)
* Exit sleep mode by outputting HIGH level to INT pin
* for 2ms~5ms.
*/
error
=
g
piod_direction_output
(
ts
->
gpiod_int
,
1
);
error
=
g
oodix_irq_direction_output
(
ts
,
1
);
if
(
error
)
return
error
;
...
...
@@ -1018,6 +1375,27 @@ static int __maybe_unused goodix_resume(struct device *dev)
if
(
error
)
return
error
;
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
])
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
"
);
return
error
;
}
error
=
goodix_send_cfg
(
ts
,
ts
->
config
,
ts
->
chip
->
config_len
);
if
(
error
)
return
error
;
}
error
=
goodix_request_irq
(
ts
);
if
(
error
)
return
error
;
...
...
@@ -1050,6 +1428,8 @@ static const struct of_device_id goodix_of_match[] = {
{
.
compatible
=
"goodix,gt911"
},
{
.
compatible
=
"goodix,gt9110"
},
{
.
compatible
=
"goodix,gt912"
},
{
.
compatible
=
"goodix,gt9147"
},
{
.
compatible
=
"goodix,gt917s"
},
{
.
compatible
=
"goodix,gt927"
},
{
.
compatible
=
"goodix,gt9271"
},
{
.
compatible
=
"goodix,gt928"
},
...
...
drivers/input/touchscreen/of_touchscreen.c
View file @
cd510679
...
...
@@ -66,7 +66,7 @@ void touchscreen_parse_properties(struct input_dev *input, bool multitouch,
{
struct
device
*
dev
=
input
->
dev
.
parent
;
struct
input_absinfo
*
absinfo
;
unsigned
int
axis
;
unsigned
int
axis
,
axis_x
,
axis_y
;
unsigned
int
minimum
,
maximum
,
fuzz
;
bool
data_present
;
...
...
@@ -74,33 +74,34 @@ void touchscreen_parse_properties(struct input_dev *input, bool multitouch,
if
(
!
input
->
absinfo
)
return
;
axis
=
multitouch
?
ABS_MT_POSITION_X
:
ABS_X
;
axis_x
=
multitouch
?
ABS_MT_POSITION_X
:
ABS_X
;
axis_y
=
multitouch
?
ABS_MT_POSITION_Y
:
ABS_Y
;
data_present
=
touchscreen_get_prop_u32
(
dev
,
"touchscreen-min-x"
,
input_abs_get_min
(
input
,
axis
),
input_abs_get_min
(
input
,
axis
_x
),
&
minimum
)
|
touchscreen_get_prop_u32
(
dev
,
"touchscreen-size-x"
,
input_abs_get_max
(
input
,
axis
)
+
1
,
axis
_x
)
+
1
,
&
maximum
)
|
touchscreen_get_prop_u32
(
dev
,
"touchscreen-fuzz-x"
,
input_abs_get_fuzz
(
input
,
axis
),
input_abs_get_fuzz
(
input
,
axis
_x
),
&
fuzz
);
if
(
data_present
)
touchscreen_set_params
(
input
,
axis
,
minimum
,
maximum
-
1
,
fuzz
);
touchscreen_set_params
(
input
,
axis
_x
,
minimum
,
maximum
-
1
,
fuzz
);
axis
=
multitouch
?
ABS_MT_POSITION_Y
:
ABS_Y
;
data_present
=
touchscreen_get_prop_u32
(
dev
,
"touchscreen-min-y"
,
input_abs_get_min
(
input
,
axis
),
input_abs_get_min
(
input
,
axis
_y
),
&
minimum
)
|
touchscreen_get_prop_u32
(
dev
,
"touchscreen-size-y"
,
input_abs_get_max
(
input
,
axis
)
+
1
,
axis
_y
)
+
1
,
&
maximum
)
|
touchscreen_get_prop_u32
(
dev
,
"touchscreen-fuzz-y"
,
input_abs_get_fuzz
(
input
,
axis
),
input_abs_get_fuzz
(
input
,
axis
_y
),
&
fuzz
);
if
(
data_present
)
touchscreen_set_params
(
input
,
axis
,
minimum
,
maximum
-
1
,
fuzz
);
touchscreen_set_params
(
input
,
axis
_y
,
minimum
,
maximum
-
1
,
fuzz
);
axis
=
multitouch
?
ABS_MT_PRESSURE
:
ABS_PRESSURE
;
data_present
=
touchscreen_get_prop_u32
(
dev
,
...
...
@@ -117,15 +118,13 @@ void touchscreen_parse_properties(struct input_dev *input, bool multitouch,
if
(
!
prop
)
return
;
axis
=
multitouch
?
ABS_MT_POSITION_X
:
ABS_X
;
prop
->
max_x
=
input_abs_get_max
(
input
,
axis
);
prop
->
max_y
=
input_abs_get_max
(
input
,
axis
+
1
);
prop
->
max_x
=
input_abs_get_max
(
input
,
axis_x
);
prop
->
max_y
=
input_abs_get_max
(
input
,
axis_y
);
prop
->
invert_x
=
device_property_read_bool
(
dev
,
"touchscreen-inverted-x"
);
if
(
prop
->
invert_x
)
{
absinfo
=
&
input
->
absinfo
[
axis
];
absinfo
=
&
input
->
absinfo
[
axis
_x
];
absinfo
->
maximum
-=
absinfo
->
minimum
;
absinfo
->
minimum
=
0
;
}
...
...
@@ -133,7 +132,7 @@ void touchscreen_parse_properties(struct input_dev *input, bool multitouch,
prop
->
invert_y
=
device_property_read_bool
(
dev
,
"touchscreen-inverted-y"
);
if
(
prop
->
invert_y
)
{
absinfo
=
&
input
->
absinfo
[
axis
+
1
];
absinfo
=
&
input
->
absinfo
[
axis
_y
];
absinfo
->
maximum
-=
absinfo
->
minimum
;
absinfo
->
minimum
=
0
;
}
...
...
@@ -141,7 +140,7 @@ void touchscreen_parse_properties(struct input_dev *input, bool multitouch,
prop
->
swap_x_y
=
device_property_read_bool
(
dev
,
"touchscreen-swapped-x-y"
);
if
(
prop
->
swap_x_y
)
swap
(
input
->
absinfo
[
axis
],
input
->
absinfo
[
axis
+
1
]);
swap
(
input
->
absinfo
[
axis
_x
],
input
->
absinfo
[
axis_y
]);
}
EXPORT_SYMBOL
(
touchscreen_parse_properties
);
...
...
include/uapi/linux/input-event-codes.h
View file @
cd510679
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/* SPDX-License-Identifier: GPL-2.0
-only
WITH Linux-syscall-note */
/*
* Input event codes
*
...
...
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