Skip to content

Commit 86f6710

Browse files
author
Jiri Kosina
committed
Merge branch 'for-5.20/elan' into for-linus
- support for Elan eKTH6915 touchscreens (Douglas Anderson)
2 parents ebf9551 + bd3cba0 commit 86f6710

File tree

4 files changed

+211
-0
lines changed

4 files changed

+211
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: http://devicetree.org/schemas/input/elan,ekth6915.yaml#
5+
$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+
title: Elan eKTH6915 touchscreen controller
8+
9+
maintainers:
10+
- Douglas Anderson <[email protected]>
11+
12+
description:
13+
Supports the Elan eKTH6915 touchscreen controller.
14+
This touchscreen controller uses the i2c-hid protocol with a reset GPIO.
15+
16+
properties:
17+
compatible:
18+
items:
19+
- const: elan,ekth6915
20+
21+
reg:
22+
const: 0x10
23+
24+
interrupts:
25+
maxItems: 1
26+
27+
reset-gpios:
28+
description: Reset GPIO; not all touchscreens using eKTH6915 hook this up.
29+
30+
vcc33-supply:
31+
description: The 3.3V supply to the touchscreen.
32+
33+
vccio-supply:
34+
description:
35+
The IO supply to the touchscreen. Need not be specified if this is the
36+
same as the 3.3V supply.
37+
38+
required:
39+
- compatible
40+
- reg
41+
- interrupts
42+
- vcc33-supply
43+
44+
additionalProperties: false
45+
46+
examples:
47+
- |
48+
#include <dt-bindings/gpio/gpio.h>
49+
#include <dt-bindings/interrupt-controller/irq.h>
50+
51+
i2c {
52+
#address-cells = <1>;
53+
#size-cells = <0>;
54+
55+
ap_ts: touchscreen@10 {
56+
compatible = "elan,ekth6915";
57+
reg = <0x10>;
58+
59+
interrupt-parent = <&tlmm>;
60+
interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
61+
62+
reset-gpios = <&tlmm 8 GPIO_ACTIVE_LOW>;
63+
vcc33-supply = <&pp3300_ts>;
64+
};
65+
};

drivers/hid/i2c-hid/Kconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,21 @@ config I2C_HID_OF
3232
will be called i2c-hid-of. It will also build/depend on the
3333
module i2c-hid.
3434

35+
config I2C_HID_OF_ELAN
36+
tristate "Driver for Elan hid-i2c based devices on OF systems"
37+
default n
38+
depends on I2C && INPUT && OF
39+
help
40+
Say Y here if you want support for Elan i2c devices that use
41+
the i2c-hid protocol on Open Firmware (Device Tree)-based
42+
systems.
43+
44+
If unsure, say N.
45+
46+
This support is also available as a module. If so, the module
47+
will be called i2c-hid-of-elan. It will also build/depend on
48+
the module i2c-hid.
49+
3550
config I2C_HID_OF_GOODIX
3651
tristate "Driver for Goodix hid-i2c based devices on OF systems"
3752
default n

drivers/hid/i2c-hid/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ i2c-hid-$(CONFIG_DMI) += i2c-hid-dmi-quirks.o
1010

1111
obj-$(CONFIG_I2C_HID_ACPI) += i2c-hid-acpi.o
1212
obj-$(CONFIG_I2C_HID_OF) += i2c-hid-of.o
13+
obj-$(CONFIG_I2C_HID_OF_ELAN) += i2c-hid-of-elan.o
1314
obj-$(CONFIG_I2C_HID_OF_GOODIX) += i2c-hid-of-goodix.o

drivers/hid/i2c-hid/i2c-hid-of-elan.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Driver for Elan touchscreens that use the i2c-hid protocol.
4+
*
5+
* Copyright 2020 Google LLC
6+
*/
7+
8+
#include <linux/delay.h>
9+
#include <linux/device.h>
10+
#include <linux/gpio/consumer.h>
11+
#include <linux/i2c.h>
12+
#include <linux/kernel.h>
13+
#include <linux/module.h>
14+
#include <linux/of.h>
15+
#include <linux/pm.h>
16+
#include <linux/regulator/consumer.h>
17+
18+
#include "i2c-hid.h"
19+
20+
struct elan_i2c_hid_chip_data {
21+
unsigned int post_gpio_reset_delay_ms;
22+
unsigned int post_power_delay_ms;
23+
u16 hid_descriptor_address;
24+
};
25+
26+
struct i2c_hid_of_elan {
27+
struct i2chid_ops ops;
28+
29+
struct regulator *vcc33;
30+
struct regulator *vccio;
31+
struct gpio_desc *reset_gpio;
32+
const struct elan_i2c_hid_chip_data *chip_data;
33+
};
34+
35+
static int elan_i2c_hid_power_up(struct i2chid_ops *ops)
36+
{
37+
struct i2c_hid_of_elan *ihid_elan =
38+
container_of(ops, struct i2c_hid_of_elan, ops);
39+
int ret;
40+
41+
ret = regulator_enable(ihid_elan->vcc33);
42+
if (ret)
43+
return ret;
44+
45+
ret = regulator_enable(ihid_elan->vccio);
46+
if (ret) {
47+
regulator_disable(ihid_elan->vcc33);
48+
return ret;
49+
}
50+
51+
if (ihid_elan->chip_data->post_power_delay_ms)
52+
msleep(ihid_elan->chip_data->post_power_delay_ms);
53+
54+
gpiod_set_value_cansleep(ihid_elan->reset_gpio, 0);
55+
if (ihid_elan->chip_data->post_gpio_reset_delay_ms)
56+
msleep(ihid_elan->chip_data->post_gpio_reset_delay_ms);
57+
58+
return 0;
59+
}
60+
61+
static void elan_i2c_hid_power_down(struct i2chid_ops *ops)
62+
{
63+
struct i2c_hid_of_elan *ihid_elan =
64+
container_of(ops, struct i2c_hid_of_elan, ops);
65+
66+
gpiod_set_value_cansleep(ihid_elan->reset_gpio, 1);
67+
regulator_disable(ihid_elan->vccio);
68+
regulator_disable(ihid_elan->vcc33);
69+
}
70+
71+
static int i2c_hid_of_elan_probe(struct i2c_client *client,
72+
const struct i2c_device_id *id)
73+
{
74+
struct i2c_hid_of_elan *ihid_elan;
75+
76+
ihid_elan = devm_kzalloc(&client->dev, sizeof(*ihid_elan), GFP_KERNEL);
77+
if (!ihid_elan)
78+
return -ENOMEM;
79+
80+
ihid_elan->ops.power_up = elan_i2c_hid_power_up;
81+
ihid_elan->ops.power_down = elan_i2c_hid_power_down;
82+
83+
/* Start out with reset asserted */
84+
ihid_elan->reset_gpio =
85+
devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH);
86+
if (IS_ERR(ihid_elan->reset_gpio))
87+
return PTR_ERR(ihid_elan->reset_gpio);
88+
89+
ihid_elan->vccio = devm_regulator_get(&client->dev, "vccio");
90+
if (IS_ERR(ihid_elan->vccio))
91+
return PTR_ERR(ihid_elan->vccio);
92+
93+
ihid_elan->vcc33 = devm_regulator_get(&client->dev, "vcc33");
94+
if (IS_ERR(ihid_elan->vcc33))
95+
return PTR_ERR(ihid_elan->vcc33);
96+
97+
ihid_elan->chip_data = device_get_match_data(&client->dev);
98+
99+
return i2c_hid_core_probe(client, &ihid_elan->ops,
100+
ihid_elan->chip_data->hid_descriptor_address, 0);
101+
}
102+
103+
static const struct elan_i2c_hid_chip_data elan_ekth6915_chip_data = {
104+
.post_power_delay_ms = 1,
105+
.post_gpio_reset_delay_ms = 300,
106+
.hid_descriptor_address = 0x0001,
107+
};
108+
109+
static const struct of_device_id elan_i2c_hid_of_match[] = {
110+
{ .compatible = "elan,ekth6915", .data = &elan_ekth6915_chip_data },
111+
{ }
112+
};
113+
MODULE_DEVICE_TABLE(of, elan_i2c_hid_of_match);
114+
115+
static struct i2c_driver elan_i2c_hid_ts_driver = {
116+
.driver = {
117+
.name = "i2c_hid_of_elan",
118+
.pm = &i2c_hid_core_pm,
119+
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
120+
.of_match_table = of_match_ptr(elan_i2c_hid_of_match),
121+
},
122+
.probe = i2c_hid_of_elan_probe,
123+
.remove = i2c_hid_core_remove,
124+
.shutdown = i2c_hid_core_shutdown,
125+
};
126+
module_i2c_driver(elan_i2c_hid_ts_driver);
127+
128+
MODULE_AUTHOR("Douglas Anderson <[email protected]>");
129+
MODULE_DESCRIPTION("Elan i2c-hid touchscreen driver");
130+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)