1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Driver for Novatek i2c touchscreen controller as found on 4 * the Acer Iconia One 7 B1-750 tablet. The Touchscreen controller 5 * model-number is unknown. Android calls this a "NVT-ts" touchscreen, 6 * but that may apply to other Novatek controller models too. 7 * 8 * Copyright (c) 2023 Hans de Goede <hdegoede@redhat.com> 9 */ 10 11 #include <linux/delay.h> 12 #include <linux/gpio/consumer.h> 13 #include <linux/interrupt.h> 14 #include <linux/i2c.h> 15 #include <linux/input.h> 16 #include <linux/input/mt.h> 17 #include <linux/input/touchscreen.h> 18 #include <linux/module.h> 19 20 #include <asm/unaligned.h> 21 22 #define NVT_TS_TOUCH_START 0x00 23 #define NVT_TS_TOUCH_SIZE 6 24 25 #define NVT_TS_PARAMETERS_START 0x78 26 /* These are offsets from NVT_TS_PARAMETERS_START */ 27 #define NVT_TS_PARAMS_WIDTH 0x04 28 #define NVT_TS_PARAMS_HEIGHT 0x06 29 #define NVT_TS_PARAMS_MAX_TOUCH 0x09 30 #define NVT_TS_PARAMS_MAX_BUTTONS 0x0a 31 #define NVT_TS_PARAMS_IRQ_TYPE 0x0b 32 #define NVT_TS_PARAMS_WAKE_TYPE 0x0c 33 #define NVT_TS_PARAMS_CHIP_ID 0x0e 34 #define NVT_TS_PARAMS_SIZE 0x0f 35 36 #define NVT_TS_SUPPORTED_WAKE_TYPE 0x05 37 #define NVT_TS_SUPPORTED_CHIP_ID 0x05 38 39 #define NVT_TS_MAX_TOUCHES 10 40 #define NVT_TS_MAX_SIZE 4096 41 42 #define NVT_TS_TOUCH_INVALID 0xff 43 #define NVT_TS_TOUCH_SLOT_SHIFT 3 44 #define NVT_TS_TOUCH_TYPE_MASK GENMASK(2, 0) 45 #define NVT_TS_TOUCH_NEW 1 46 #define NVT_TS_TOUCH_UPDATE 2 47 #define NVT_TS_TOUCH_RELEASE 3 48 49 static const int nvt_ts_irq_type[4] = { 50 IRQF_TRIGGER_RISING, 51 IRQF_TRIGGER_FALLING, 52 IRQF_TRIGGER_LOW, 53 IRQF_TRIGGER_HIGH 54 }; 55 56 struct nvt_ts_data { 57 struct i2c_client *client; 58 struct input_dev *input; 59 struct gpio_desc *reset_gpio; 60 struct touchscreen_properties prop; 61 int max_touches; 62 u8 buf[NVT_TS_TOUCH_SIZE * NVT_TS_MAX_TOUCHES]; 63 }; 64 65 static int nvt_ts_read_data(struct i2c_client *client, u8 reg, u8 *data, int count) 66 { 67 struct i2c_msg msg[2] = { 68 { 69 .addr = client->addr, 70 .len = 1, 71 .buf = ®, 72 }, 73 { 74 .addr = client->addr, 75 .flags = I2C_M_RD, 76 .len = count, 77 .buf = data, 78 } 79 }; 80 int ret; 81 82 ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); 83 if (ret != ARRAY_SIZE(msg)) { 84 dev_err(&client->dev, "Error reading from 0x%02x: %d\n", reg, ret); 85 return (ret < 0) ? ret : -EIO; 86 } 87 88 return 0; 89 } 90 91 static irqreturn_t nvt_ts_irq(int irq, void *dev_id) 92 { 93 struct nvt_ts_data *data = dev_id; 94 struct device *dev = &data->client->dev; 95 int i, error, slot, x, y; 96 bool active; 97 u8 *touch; 98 99 error = nvt_ts_read_data(data->client, NVT_TS_TOUCH_START, data->buf, 100 data->max_touches * NVT_TS_TOUCH_SIZE); 101 if (error) 102 return IRQ_HANDLED; 103 104 for (i = 0; i < data->max_touches; i++) { 105 touch = &data->buf[i * NVT_TS_TOUCH_SIZE]; 106 107 if (touch[0] == NVT_TS_TOUCH_INVALID) 108 continue; 109 110 slot = touch[0] >> NVT_TS_TOUCH_SLOT_SHIFT; 111 if (slot < 1 || slot > data->max_touches) { 112 dev_warn(dev, "slot %d out of range, ignoring\n", slot); 113 continue; 114 } 115 116 switch (touch[0] & NVT_TS_TOUCH_TYPE_MASK) { 117 case NVT_TS_TOUCH_NEW: 118 case NVT_TS_TOUCH_UPDATE: 119 active = true; 120 break; 121 case NVT_TS_TOUCH_RELEASE: 122 active = false; 123 break; 124 default: 125 dev_warn(dev, "slot %d unknown state %d\n", slot, touch[0] & 7); 126 continue; 127 } 128 129 slot--; 130 x = (touch[1] << 4) | (touch[3] >> 4); 131 y = (touch[2] << 4) | (touch[3] & 0x0f); 132 133 input_mt_slot(data->input, slot); 134 input_mt_report_slot_state(data->input, MT_TOOL_FINGER, active); 135 touchscreen_report_pos(data->input, &data->prop, x, y, true); 136 } 137 138 input_mt_sync_frame(data->input); 139 input_sync(data->input); 140 141 return IRQ_HANDLED; 142 } 143 144 static int nvt_ts_start(struct input_dev *dev) 145 { 146 struct nvt_ts_data *data = input_get_drvdata(dev); 147 148 enable_irq(data->client->irq); 149 gpiod_set_value_cansleep(data->reset_gpio, 0); 150 151 return 0; 152 } 153 154 static void nvt_ts_stop(struct input_dev *dev) 155 { 156 struct nvt_ts_data *data = input_get_drvdata(dev); 157 158 disable_irq(data->client->irq); 159 gpiod_set_value_cansleep(data->reset_gpio, 1); 160 } 161 162 static int nvt_ts_suspend(struct device *dev) 163 { 164 struct nvt_ts_data *data = i2c_get_clientdata(to_i2c_client(dev)); 165 166 mutex_lock(&data->input->mutex); 167 if (input_device_enabled(data->input)) 168 nvt_ts_stop(data->input); 169 mutex_unlock(&data->input->mutex); 170 171 return 0; 172 } 173 174 static int nvt_ts_resume(struct device *dev) 175 { 176 struct nvt_ts_data *data = i2c_get_clientdata(to_i2c_client(dev)); 177 178 mutex_lock(&data->input->mutex); 179 if (input_device_enabled(data->input)) 180 nvt_ts_start(data->input); 181 mutex_unlock(&data->input->mutex); 182 183 return 0; 184 } 185 186 static DEFINE_SIMPLE_DEV_PM_OPS(nvt_ts_pm_ops, nvt_ts_suspend, nvt_ts_resume); 187 188 static int nvt_ts_probe(struct i2c_client *client) 189 { 190 struct device *dev = &client->dev; 191 int error, width, height, irq_type; 192 struct nvt_ts_data *data; 193 struct input_dev *input; 194 195 if (!client->irq) { 196 dev_err(dev, "Error no irq specified\n"); 197 return -EINVAL; 198 } 199 200 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 201 if (!data) 202 return -ENOMEM; 203 204 data->client = client; 205 i2c_set_clientdata(client, data); 206 207 data->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 208 error = PTR_ERR_OR_ZERO(data->reset_gpio); 209 if (error) { 210 dev_err(dev, "failed to request reset GPIO: %d\n", error); 211 return error; 212 } 213 214 /* Wait for controller to come out of reset before params read */ 215 msleep(100); 216 error = nvt_ts_read_data(data->client, NVT_TS_PARAMETERS_START, 217 data->buf, NVT_TS_PARAMS_SIZE); 218 gpiod_set_value_cansleep(data->reset_gpio, 1); /* Put back in reset */ 219 if (error) 220 return error; 221 222 width = get_unaligned_be16(&data->buf[NVT_TS_PARAMS_WIDTH]); 223 height = get_unaligned_be16(&data->buf[NVT_TS_PARAMS_HEIGHT]); 224 data->max_touches = data->buf[NVT_TS_PARAMS_MAX_TOUCH]; 225 irq_type = data->buf[NVT_TS_PARAMS_IRQ_TYPE]; 226 227 if (width > NVT_TS_MAX_SIZE || height >= NVT_TS_MAX_SIZE || 228 data->max_touches > NVT_TS_MAX_TOUCHES || 229 irq_type >= ARRAY_SIZE(nvt_ts_irq_type) || 230 data->buf[NVT_TS_PARAMS_WAKE_TYPE] != NVT_TS_SUPPORTED_WAKE_TYPE || 231 data->buf[NVT_TS_PARAMS_CHIP_ID] != NVT_TS_SUPPORTED_CHIP_ID) { 232 dev_err(dev, "Unsupported touchscreen parameters: %*ph\n", 233 NVT_TS_PARAMS_SIZE, data->buf); 234 return -EIO; 235 } 236 237 dev_dbg(dev, "Detected %dx%d touchscreen with %d max touches\n", 238 width, height, data->max_touches); 239 240 if (data->buf[NVT_TS_PARAMS_MAX_BUTTONS]) 241 dev_warn(dev, "Touchscreen buttons are not supported\n"); 242 243 input = devm_input_allocate_device(dev); 244 if (!input) 245 return -ENOMEM; 246 247 input->name = client->name; 248 input->id.bustype = BUS_I2C; 249 input->open = nvt_ts_start; 250 input->close = nvt_ts_stop; 251 252 input_set_abs_params(input, ABS_MT_POSITION_X, 0, width - 1, 0, 0); 253 input_set_abs_params(input, ABS_MT_POSITION_Y, 0, height - 1, 0, 0); 254 touchscreen_parse_properties(input, true, &data->prop); 255 256 error = input_mt_init_slots(input, data->max_touches, 257 INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 258 if (error) 259 return error; 260 261 data->input = input; 262 input_set_drvdata(input, data); 263 264 error = devm_request_threaded_irq(dev, client->irq, NULL, nvt_ts_irq, 265 IRQF_ONESHOT | IRQF_NO_AUTOEN | 266 nvt_ts_irq_type[irq_type], 267 client->name, data); 268 if (error) { 269 dev_err(dev, "failed to request irq: %d\n", error); 270 return error; 271 } 272 273 error = input_register_device(input); 274 if (error) { 275 dev_err(dev, "failed to request irq: %d\n", error); 276 return error; 277 } 278 279 return 0; 280 } 281 282 static const struct i2c_device_id nvt_ts_i2c_id[] = { 283 { "NVT-ts" }, 284 { } 285 }; 286 MODULE_DEVICE_TABLE(i2c, nvt_ts_i2c_id); 287 288 static struct i2c_driver nvt_ts_driver = { 289 .driver = { 290 .name = "novatek-nvt-ts", 291 .pm = pm_sleep_ptr(&nvt_ts_pm_ops), 292 }, 293 .probe = nvt_ts_probe, 294 .id_table = nvt_ts_i2c_id, 295 }; 296 297 module_i2c_driver(nvt_ts_driver); 298 299 MODULE_DESCRIPTION("Novatek NVT-ts touchscreen driver"); 300 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 301 MODULE_LICENSE("GPL"); 302