Skip to content

Commit 4d395cb

Browse files
Gelbpunktdtor
authored andcommitted
Input: goodix_berlin - add support for Berlin-A series
The current implementation of the goodix_berlin driver lacks support for revisions A and B of the Berlin IC. This change adds support for the gt9897 IC, which is a Berlin-A revision part. The differences between revision D and A are rather minor, a handful of address changes and a slightly larger read buffer. They were taken from the driver published by Goodix, which does a few more things that don't appear to be necessary for the touchscreen to work properly. Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org> Tested-by: Luca Weiss <luca.weiss@fairphone.com> Signed-off-by: Jens Reidel <adrian@mainlining.org> Link: https://lore.kernel.org/r/20250309062315.35720-3-adrian@mainlining.org Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
1 parent 8d27642 commit 4d395cb

File tree

4 files changed

+73
-26
lines changed

4 files changed

+73
-26
lines changed

drivers/input/touchscreen/goodix_berlin.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,26 @@
1212

1313
#include <linux/pm.h>
1414

15+
#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR_A 0x1000C
16+
#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D 0x10014
17+
18+
#define GOODIX_BERLIN_IC_INFO_ADDR_A 0x10068
19+
#define GOODIX_BERLIN_IC_INFO_ADDR_D 0x10070
20+
21+
struct goodix_berlin_ic_data {
22+
int fw_version_info_addr;
23+
int ic_info_addr;
24+
ssize_t read_dummy_len;
25+
ssize_t read_prefix_len;
26+
};
27+
1528
struct device;
1629
struct input_id;
1730
struct regmap;
1831

1932
int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id,
20-
struct regmap *regmap);
33+
struct regmap *regmap,
34+
const struct goodix_berlin_ic_data *ic_data);
2135

2236
extern const struct dev_pm_ops goodix_berlin_pm_ops;
2337
extern const struct attribute_group *goodix_berlin_groups[];

drivers/input/touchscreen/goodix_berlin_core.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,23 @@
1212
* to the previous generations.
1313
*
1414
* Currently the driver only handles Multitouch events with already
15-
* programmed firmware and "config" for "Revision D" Berlin IC.
15+
* programmed firmware and "config" for "Revision A/D" Berlin IC.
1616
*
1717
* Support is missing for:
1818
* - ESD Management
1919
* - Firmware update/flashing
2020
* - "Config" update/flashing
2121
* - Stylus Events
2222
* - Gesture Events
23-
* - Support for older revisions (A & B)
23+
* - Support for revision B
2424
*/
2525

2626
#include <linux/bitfield.h>
2727
#include <linux/gpio/consumer.h>
2828
#include <linux/input.h>
2929
#include <linux/input/mt.h>
3030
#include <linux/input/touchscreen.h>
31+
#include <linux/property.h>
3132
#include <linux/regmap.h>
3233
#include <linux/regulator/consumer.h>
3334
#include <linux/sizes.h>
@@ -53,10 +54,8 @@
5354

5455
#define GOODIX_BERLIN_DEV_CONFIRM_VAL 0xAA
5556
#define GOODIX_BERLIN_BOOTOPTION_ADDR 0x10000
56-
#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR 0x10014
5757

5858
#define GOODIX_BERLIN_IC_INFO_MAX_LEN SZ_1K
59-
#define GOODIX_BERLIN_IC_INFO_ADDR 0x10070
6059

6160
#define GOODIX_BERLIN_CHECKSUM_SIZE sizeof(u16)
6261

@@ -175,6 +174,8 @@ struct goodix_berlin_core {
175174
/* Runtime parameters extracted from IC_INFO buffer */
176175
u32 touch_data_addr;
177176

177+
const struct goodix_berlin_ic_data *ic_data;
178+
178179
struct goodix_berlin_event event;
179180
};
180181

@@ -299,7 +300,7 @@ static int goodix_berlin_read_version(struct goodix_berlin_core *cd)
299300
{
300301
int error;
301302

302-
error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_FW_VERSION_INFO_ADDR,
303+
error = regmap_raw_read(cd->regmap, cd->ic_data->fw_version_info_addr,
303304
&cd->fw_version, sizeof(cd->fw_version));
304305
if (error) {
305306
dev_err(cd->dev, "error reading fw version, %d\n", error);
@@ -367,7 +368,7 @@ static int goodix_berlin_get_ic_info(struct goodix_berlin_core *cd)
367368
if (!afe_data)
368369
return -ENOMEM;
369370

370-
error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_IC_INFO_ADDR,
371+
error = regmap_raw_read(cd->regmap, cd->ic_data->ic_info_addr,
371372
&length_raw, sizeof(length_raw));
372373
if (error) {
373374
dev_err(cd->dev, "failed get ic info length, %d\n", error);
@@ -380,8 +381,8 @@ static int goodix_berlin_get_ic_info(struct goodix_berlin_core *cd)
380381
return -EINVAL;
381382
}
382383

383-
error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_IC_INFO_ADDR,
384-
afe_data, length);
384+
error = regmap_raw_read(cd->regmap, cd->ic_data->ic_info_addr, afe_data,
385+
length);
385386
if (error) {
386387
dev_err(cd->dev, "failed get ic info data, %d\n", error);
387388
return error;
@@ -716,7 +717,8 @@ const struct attribute_group *goodix_berlin_groups[] = {
716717
EXPORT_SYMBOL_GPL(goodix_berlin_groups);
717718

718719
int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id,
719-
struct regmap *regmap)
720+
struct regmap *regmap,
721+
const struct goodix_berlin_ic_data *ic_data)
720722
{
721723
struct goodix_berlin_core *cd;
722724
int error;
@@ -733,6 +735,7 @@ int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id,
733735
cd->dev = dev;
734736
cd->regmap = regmap;
735737
cd->irq = irq;
738+
cd->ic_data = ic_data;
736739

737740
cd->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
738741
if (IS_ERR(cd->reset_gpio))

drivers/input/touchscreen/goodix_berlin_i2c.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ static const struct input_id goodix_berlin_i2c_input_id = {
3131

3232
static int goodix_berlin_i2c_probe(struct i2c_client *client)
3333
{
34+
const struct goodix_berlin_ic_data *ic_data =
35+
i2c_get_match_data(client);
3436
struct regmap *regmap;
3537
int error;
3638

@@ -39,22 +41,28 @@ static int goodix_berlin_i2c_probe(struct i2c_client *client)
3941
return PTR_ERR(regmap);
4042

4143
error = goodix_berlin_probe(&client->dev, client->irq,
42-
&goodix_berlin_i2c_input_id, regmap);
44+
&goodix_berlin_i2c_input_id, regmap,
45+
ic_data);
4346
if (error)
4447
return error;
4548

4649
return 0;
4750
}
4851

52+
static const struct goodix_berlin_ic_data gt9916_data = {
53+
.fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D,
54+
.ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_D,
55+
};
56+
4957
static const struct i2c_device_id goodix_berlin_i2c_id[] = {
50-
{ "gt9916" },
58+
{ .name = "gt9916", .driver_data = (long)&gt9916_data },
5159
{ }
5260
};
5361

5462
MODULE_DEVICE_TABLE(i2c, goodix_berlin_i2c_id);
5563

5664
static const struct of_device_id goodix_berlin_i2c_of_match[] = {
57-
{ .compatible = "goodix,gt9916", },
65+
{ .compatible = "goodix,gt9916", .data = &gt9916_data },
5866
{ }
5967
};
6068
MODULE_DEVICE_TABLE(of, goodix_berlin_i2c_of_match);

drivers/input/touchscreen/goodix_berlin_spi.c

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@
1818

1919
#define GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN 1
2020
#define GOODIX_BERLIN_REGISTER_WIDTH 4
21-
#define GOODIX_BERLIN_SPI_READ_DUMMY_LEN 3
22-
#define GOODIX_BERLIN_SPI_READ_PREFIX_LEN (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \
21+
#define GOODIX_BERLIN_SPI_READ_DUMMY_LEN_A 4
22+
#define GOODIX_BERLIN_SPI_READ_DUMMY_LEN_D 3
23+
#define GOODIX_BERLIN_SPI_READ_PREFIX_LEN_A (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \
2324
GOODIX_BERLIN_REGISTER_WIDTH + \
24-
GOODIX_BERLIN_SPI_READ_DUMMY_LEN)
25+
GOODIX_BERLIN_SPI_READ_DUMMY_LEN_A)
26+
#define GOODIX_BERLIN_SPI_READ_PREFIX_LEN_D (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \
27+
GOODIX_BERLIN_REGISTER_WIDTH + \
28+
GOODIX_BERLIN_SPI_READ_DUMMY_LEN_D)
2529
#define GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \
2630
GOODIX_BERLIN_REGISTER_WIDTH)
2731

@@ -33,6 +37,7 @@ static int goodix_berlin_spi_read(void *context, const void *reg_buf,
3337
size_t val_size)
3438
{
3539
struct spi_device *spi = context;
40+
const struct goodix_berlin_ic_data *ic_data = spi_get_device_match_data(spi);
3641
struct spi_transfer xfers;
3742
struct spi_message spi_msg;
3843
const u32 *reg = reg_buf; /* reg is stored as native u32 at start of buffer */
@@ -42,23 +47,22 @@ static int goodix_berlin_spi_read(void *context, const void *reg_buf,
4247
return -EINVAL;
4348

4449
u8 *buf __free(kfree) =
45-
kzalloc(GOODIX_BERLIN_SPI_READ_PREFIX_LEN + val_size,
46-
GFP_KERNEL);
50+
kzalloc(ic_data->read_prefix_len + val_size, GFP_KERNEL);
4751
if (!buf)
4852
return -ENOMEM;
4953

5054
spi_message_init(&spi_msg);
5155
memset(&xfers, 0, sizeof(xfers));
5256

53-
/* buffer format: 0xF1 + addr(4bytes) + dummy(3bytes) + data */
57+
/* buffer format: 0xF1 + addr(4bytes) + dummy(3/4bytes) + data */
5458
buf[0] = GOODIX_BERLIN_SPI_READ_FLAG;
5559
put_unaligned_be32(*reg, buf + GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN);
5660
memset(buf + GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + GOODIX_BERLIN_REGISTER_WIDTH,
57-
0xff, GOODIX_BERLIN_SPI_READ_DUMMY_LEN);
61+
0xff, ic_data->read_dummy_len);
5862

5963
xfers.tx_buf = buf;
6064
xfers.rx_buf = buf;
61-
xfers.len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN + val_size;
65+
xfers.len = ic_data->read_prefix_len + val_size;
6266
xfers.cs_change = 0;
6367
spi_message_add_tail(&xfers, &spi_msg);
6468

@@ -68,7 +72,7 @@ static int goodix_berlin_spi_read(void *context, const void *reg_buf,
6872
return error;
6973
}
7074

71-
memcpy(val_buf, buf + GOODIX_BERLIN_SPI_READ_PREFIX_LEN, val_size);
75+
memcpy(val_buf, buf + ic_data->read_prefix_len, val_size);
7276
return error;
7377
}
7478

@@ -123,6 +127,7 @@ static const struct input_id goodix_berlin_spi_input_id = {
123127

124128
static int goodix_berlin_spi_probe(struct spi_device *spi)
125129
{
130+
const struct goodix_berlin_ic_data *ic_data = spi_get_device_match_data(spi);
126131
struct regmap_config regmap_config;
127132
struct regmap *regmap;
128133
size_t max_size;
@@ -137,29 +142,46 @@ static int goodix_berlin_spi_probe(struct spi_device *spi)
137142
max_size = spi_max_transfer_size(spi);
138143

139144
regmap_config = goodix_berlin_spi_regmap_conf;
140-
regmap_config.max_raw_read = max_size - GOODIX_BERLIN_SPI_READ_PREFIX_LEN;
145+
regmap_config.max_raw_read = max_size - ic_data->read_prefix_len;
141146
regmap_config.max_raw_write = max_size - GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN;
142147

143148
regmap = devm_regmap_init(&spi->dev, NULL, spi, &regmap_config);
144149
if (IS_ERR(regmap))
145150
return PTR_ERR(regmap);
146151

147152
error = goodix_berlin_probe(&spi->dev, spi->irq,
148-
&goodix_berlin_spi_input_id, regmap);
153+
&goodix_berlin_spi_input_id, regmap,
154+
ic_data);
149155
if (error)
150156
return error;
151157

152158
return 0;
153159
}
154160

161+
static const struct goodix_berlin_ic_data gt9897_data = {
162+
.fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_A,
163+
.ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_A,
164+
.read_dummy_len = GOODIX_BERLIN_SPI_READ_DUMMY_LEN_A,
165+
.read_prefix_len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN_A,
166+
};
167+
168+
static const struct goodix_berlin_ic_data gt9916_data = {
169+
.fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D,
170+
.ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_D,
171+
.read_dummy_len = GOODIX_BERLIN_SPI_READ_DUMMY_LEN_D,
172+
.read_prefix_len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN_D,
173+
};
174+
155175
static const struct spi_device_id goodix_berlin_spi_ids[] = {
156-
{ "gt9916" },
176+
{ .name = "gt9897", .driver_data = (long)&gt9897_data },
177+
{ .name = "gt9916", .driver_data = (long)&gt9916_data },
157178
{ },
158179
};
159180
MODULE_DEVICE_TABLE(spi, goodix_berlin_spi_ids);
160181

161182
static const struct of_device_id goodix_berlin_spi_of_match[] = {
162-
{ .compatible = "goodix,gt9916", },
183+
{ .compatible = "goodix,gt9897", .data = &gt9897_data },
184+
{ .compatible = "goodix,gt9916", .data = &gt9916_data },
163185
{ }
164186
};
165187
MODULE_DEVICE_TABLE(of, goodix_berlin_spi_of_match);

0 commit comments

Comments
 (0)