Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Jens Reidel and committed by
Dmitry Torokhov
4d395cb0 8d276425

+73 -26
+15 -1
drivers/input/touchscreen/goodix_berlin.h
··· 12 12 13 13 #include <linux/pm.h> 14 14 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 + 15 28 struct device; 16 29 struct input_id; 17 30 struct regmap; 18 31 19 32 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); 21 35 22 36 extern const struct dev_pm_ops goodix_berlin_pm_ops; 23 37 extern const struct attribute_group *goodix_berlin_groups[];
+12 -9
drivers/input/touchscreen/goodix_berlin_core.c
··· 12 12 * to the previous generations. 13 13 * 14 14 * 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. 16 16 * 17 17 * Support is missing for: 18 18 * - ESD Management ··· 20 20 * - "Config" update/flashing 21 21 * - Stylus Events 22 22 * - Gesture Events 23 - * - Support for older revisions (A & B) 23 + * - Support for revision B 24 24 */ 25 25 26 26 #include <linux/bitfield.h> ··· 28 28 #include <linux/input.h> 29 29 #include <linux/input/mt.h> 30 30 #include <linux/input/touchscreen.h> 31 + #include <linux/property.h> 31 32 #include <linux/regmap.h> 32 33 #include <linux/regulator/consumer.h> 33 34 #include <linux/sizes.h> ··· 54 53 55 54 #define GOODIX_BERLIN_DEV_CONFIRM_VAL 0xAA 56 55 #define GOODIX_BERLIN_BOOTOPTION_ADDR 0x10000 57 - #define GOODIX_BERLIN_FW_VERSION_INFO_ADDR 0x10014 58 56 59 57 #define GOODIX_BERLIN_IC_INFO_MAX_LEN SZ_1K 60 - #define GOODIX_BERLIN_IC_INFO_ADDR 0x10070 61 58 62 59 #define GOODIX_BERLIN_CHECKSUM_SIZE sizeof(u16) 63 60 ··· 173 174 174 175 /* Runtime parameters extracted from IC_INFO buffer */ 175 176 u32 touch_data_addr; 177 + 178 + const struct goodix_berlin_ic_data *ic_data; 176 179 177 180 struct goodix_berlin_event event; 178 181 }; ··· 300 299 { 301 300 int error; 302 301 303 - error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_FW_VERSION_INFO_ADDR, 302 + error = regmap_raw_read(cd->regmap, cd->ic_data->fw_version_info_addr, 304 303 &cd->fw_version, sizeof(cd->fw_version)); 305 304 if (error) { 306 305 dev_err(cd->dev, "error reading fw version, %d\n", error); ··· 368 367 if (!afe_data) 369 368 return -ENOMEM; 370 369 371 - error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_IC_INFO_ADDR, 370 + error = regmap_raw_read(cd->regmap, cd->ic_data->ic_info_addr, 372 371 &length_raw, sizeof(length_raw)); 373 372 if (error) { 374 373 dev_err(cd->dev, "failed get ic info length, %d\n", error); ··· 381 380 return -EINVAL; 382 381 } 383 382 384 - error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_IC_INFO_ADDR, 385 - afe_data, length); 383 + error = regmap_raw_read(cd->regmap, cd->ic_data->ic_info_addr, afe_data, 384 + length); 386 385 if (error) { 387 386 dev_err(cd->dev, "failed get ic info data, %d\n", error); 388 387 return error; ··· 717 716 EXPORT_SYMBOL_GPL(goodix_berlin_groups); 718 717 719 718 int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id, 720 - struct regmap *regmap) 719 + struct regmap *regmap, 720 + const struct goodix_berlin_ic_data *ic_data) 721 721 { 722 722 struct goodix_berlin_core *cd; 723 723 int error; ··· 735 733 cd->dev = dev; 736 734 cd->regmap = regmap; 737 735 cd->irq = irq; 736 + cd->ic_data = ic_data; 738 737 739 738 cd->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); 740 739 if (IS_ERR(cd->reset_gpio))
+11 -3
drivers/input/touchscreen/goodix_berlin_i2c.c
··· 31 31 32 32 static int goodix_berlin_i2c_probe(struct i2c_client *client) 33 33 { 34 + const struct goodix_berlin_ic_data *ic_data = 35 + i2c_get_match_data(client); 34 36 struct regmap *regmap; 35 37 int error; 36 38 ··· 41 39 return PTR_ERR(regmap); 42 40 43 41 error = goodix_berlin_probe(&client->dev, client->irq, 44 - &goodix_berlin_i2c_input_id, regmap); 42 + &goodix_berlin_i2c_input_id, regmap, 43 + ic_data); 45 44 if (error) 46 45 return error; 47 46 48 47 return 0; 49 48 } 50 49 50 + static const struct goodix_berlin_ic_data gt9916_data = { 51 + .fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D, 52 + .ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_D, 53 + }; 54 + 51 55 static const struct i2c_device_id goodix_berlin_i2c_id[] = { 52 - { "gt9916" }, 56 + { .name = "gt9916", .driver_data = (long)&gt9916_data }, 53 57 { } 54 58 }; 55 59 56 60 MODULE_DEVICE_TABLE(i2c, goodix_berlin_i2c_id); 57 61 58 62 static const struct of_device_id goodix_berlin_i2c_of_match[] = { 59 - { .compatible = "goodix,gt9916", }, 63 + { .compatible = "goodix,gt9916", .data = &gt9916_data }, 60 64 { } 61 65 }; 62 66 MODULE_DEVICE_TABLE(of, goodix_berlin_i2c_of_match);
+35 -13
drivers/input/touchscreen/goodix_berlin_spi.c
··· 18 18 19 19 #define GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN 1 20 20 #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 + \ 23 24 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) 25 29 #define GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \ 26 30 GOODIX_BERLIN_REGISTER_WIDTH) 27 31 ··· 37 33 size_t val_size) 38 34 { 39 35 struct spi_device *spi = context; 36 + const struct goodix_berlin_ic_data *ic_data = spi_get_device_match_data(spi); 40 37 struct spi_transfer xfers; 41 38 struct spi_message spi_msg; 42 39 const u32 *reg = reg_buf; /* reg is stored as native u32 at start of buffer */ ··· 47 42 return -EINVAL; 48 43 49 44 u8 *buf __free(kfree) = 50 - kzalloc(GOODIX_BERLIN_SPI_READ_PREFIX_LEN + val_size, 51 - GFP_KERNEL); 45 + kzalloc(ic_data->read_prefix_len + val_size, GFP_KERNEL); 52 46 if (!buf) 53 47 return -ENOMEM; 54 48 55 49 spi_message_init(&spi_msg); 56 50 memset(&xfers, 0, sizeof(xfers)); 57 51 58 - /* buffer format: 0xF1 + addr(4bytes) + dummy(3bytes) + data */ 52 + /* buffer format: 0xF1 + addr(4bytes) + dummy(3/4bytes) + data */ 59 53 buf[0] = GOODIX_BERLIN_SPI_READ_FLAG; 60 54 put_unaligned_be32(*reg, buf + GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN); 61 55 memset(buf + GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + GOODIX_BERLIN_REGISTER_WIDTH, 62 - 0xff, GOODIX_BERLIN_SPI_READ_DUMMY_LEN); 56 + 0xff, ic_data->read_dummy_len); 63 57 64 58 xfers.tx_buf = buf; 65 59 xfers.rx_buf = buf; 66 - xfers.len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN + val_size; 60 + xfers.len = ic_data->read_prefix_len + val_size; 67 61 xfers.cs_change = 0; 68 62 spi_message_add_tail(&xfers, &spi_msg); 69 63 ··· 72 68 return error; 73 69 } 74 70 75 - memcpy(val_buf, buf + GOODIX_BERLIN_SPI_READ_PREFIX_LEN, val_size); 71 + memcpy(val_buf, buf + ic_data->read_prefix_len, val_size); 76 72 return error; 77 73 } 78 74 ··· 127 123 128 124 static int goodix_berlin_spi_probe(struct spi_device *spi) 129 125 { 126 + const struct goodix_berlin_ic_data *ic_data = spi_get_device_match_data(spi); 130 127 struct regmap_config regmap_config; 131 128 struct regmap *regmap; 132 129 size_t max_size; ··· 142 137 max_size = spi_max_transfer_size(spi); 143 138 144 139 regmap_config = goodix_berlin_spi_regmap_conf; 145 - regmap_config.max_raw_read = max_size - GOODIX_BERLIN_SPI_READ_PREFIX_LEN; 140 + regmap_config.max_raw_read = max_size - ic_data->read_prefix_len; 146 141 regmap_config.max_raw_write = max_size - GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN; 147 142 148 143 regmap = devm_regmap_init(&spi->dev, NULL, spi, &regmap_config); ··· 150 145 return PTR_ERR(regmap); 151 146 152 147 error = goodix_berlin_probe(&spi->dev, spi->irq, 153 - &goodix_berlin_spi_input_id, regmap); 148 + &goodix_berlin_spi_input_id, regmap, 149 + ic_data); 154 150 if (error) 155 151 return error; 156 152 157 153 return 0; 158 154 } 159 155 156 + static const struct goodix_berlin_ic_data gt9897_data = { 157 + .fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_A, 158 + .ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_A, 159 + .read_dummy_len = GOODIX_BERLIN_SPI_READ_DUMMY_LEN_A, 160 + .read_prefix_len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN_A, 161 + }; 162 + 163 + static const struct goodix_berlin_ic_data gt9916_data = { 164 + .fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D, 165 + .ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_D, 166 + .read_dummy_len = GOODIX_BERLIN_SPI_READ_DUMMY_LEN_D, 167 + .read_prefix_len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN_D, 168 + }; 169 + 160 170 static const struct spi_device_id goodix_berlin_spi_ids[] = { 161 - { "gt9916" }, 171 + { .name = "gt9897", .driver_data = (long)&gt9897_data }, 172 + { .name = "gt9916", .driver_data = (long)&gt9916_data }, 162 173 { }, 163 174 }; 164 175 MODULE_DEVICE_TABLE(spi, goodix_berlin_spi_ids); 165 176 166 177 static const struct of_device_id goodix_berlin_spi_of_match[] = { 167 - { .compatible = "goodix,gt9916", }, 178 + { .compatible = "goodix,gt9897", .data = &gt9897_data }, 179 + { .compatible = "goodix,gt9916", .data = &gt9916_data }, 168 180 { } 169 181 }; 170 182 MODULE_DEVICE_TABLE(of, goodix_berlin_spi_of_match);