1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Wacom W9000-series penabled I2C touchscreen driver
4 *
5 * Copyright (c) 2026 Hendrik Noack <hendrik-noack@gmx.de>
6 *
7 * Partially based on vendor driver:
8 * Copyright (C) 2012, Samsung Electronics Co. Ltd.
9 */
10
11 #include <linux/delay.h>
12 #include <linux/gpio/consumer.h>
13 #include <linux/i2c.h>
14 #include <linux/input.h>
15 #include <linux/input/touchscreen.h>
16 #include <linux/interrupt.h>
17 #include <linux/lockdep.h>
18 #include <linux/regulator/consumer.h>
19 #include <linux/unaligned.h>
20
21 /* Some chips have flaky firmware that requires many retries before responding. */
22 #define CMD_QUERY_RETRIES 8
23
24 /* Message length */
25 #define CMD_QUERY_NUM_MAX 9
26 #define MSG_COORD_NUM_MAX 12
27
28 /* Commands */
29 #define CMD_QUERY 0x2a
30
31 struct wacom_w9000_variant {
32 const u8 cmd_query_num;
33 const u8 msg_coord_num;
34 const char *name;
35 };
36
37 struct wacom_w9000_data {
38 struct i2c_client *client;
39 struct input_dev *input_dev;
40 const struct wacom_w9000_variant *variant;
41 u16 fw_version;
42
43 struct touchscreen_properties prop;
44 u16 max_pressure;
45
46 struct regulator *regulator;
47
48 struct gpio_desc *flash_mode_gpio;
49 struct gpio_desc *reset_gpio;
50
51 unsigned int irq;
52
53 bool pen_proximity;
54 };
55
wacom_w9000_read(struct i2c_client * client,u8 command,u8 len,u8 * data)56 static int wacom_w9000_read(struct i2c_client *client, u8 command, u8 len, u8 *data)
57 {
58 int error, res;
59 struct i2c_msg msg[] = {
60 {
61 .addr = client->addr,
62 .flags = 0,
63 .buf = &command,
64 .len = sizeof(command),
65 }, {
66 .addr = client->addr,
67 .flags = I2C_M_RD,
68 .buf = data,
69 .len = len,
70 }
71 };
72
73 res = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
74 if (res != ARRAY_SIZE(msg)) {
75 error = res < 0 ? res : -EIO;
76 dev_err(&client->dev, "%s: i2c transfer failed: %d (%d)\n",
77 __func__, error, res);
78 return error;
79 }
80
81 return 0;
82 }
83
wacom_w9000_query(struct wacom_w9000_data * wacom_data)84 static int wacom_w9000_query(struct wacom_w9000_data *wacom_data)
85 {
86 struct i2c_client *client = wacom_data->client;
87 struct device *dev = &wacom_data->client->dev;
88 u8 data[CMD_QUERY_NUM_MAX];
89 int retry;
90 int error;
91
92 for (retry = 0; retry < CMD_QUERY_RETRIES; retry++) {
93 error = wacom_w9000_read(client, CMD_QUERY,
94 wacom_data->variant->cmd_query_num,
95 data);
96 if (!error && data[0] == 0x0f)
97 break;
98 }
99
100 if (error)
101 return error;
102
103 if (data[0] != 0x0f)
104 return -EIO;
105
106 dev_dbg(dev, "query: %*ph, %d\n",
107 wacom_data->variant->cmd_query_num, data, retry);
108
109 wacom_data->prop.max_x = get_unaligned_be16(&data[1]);
110 wacom_data->prop.max_y = get_unaligned_be16(&data[3]);
111 wacom_data->max_pressure = get_unaligned_be16(&data[5]);
112 wacom_data->fw_version = get_unaligned_be16(&data[7]);
113
114 dev_dbg(dev, "max_x:%d, max_y:%d, max_pressure:%d, fw:%#x\n",
115 wacom_data->prop.max_x, wacom_data->prop.max_y,
116 wacom_data->max_pressure, wacom_data->fw_version);
117
118 return 0;
119 }
120
wacom_w9000_power_on(struct wacom_w9000_data * wacom_data)121 static int wacom_w9000_power_on(struct wacom_w9000_data *wacom_data)
122 {
123 int error;
124
125 lockdep_assert_held(&wacom_data->input_dev->mutex);
126
127 error = regulator_enable(wacom_data->regulator);
128 if (error) {
129 dev_err(&wacom_data->client->dev, "Failed to enable regulators: %d\n", error);
130 return error;
131 }
132
133 msleep(200);
134
135 gpiod_set_value_cansleep(wacom_data->reset_gpio, 0);
136 enable_irq(wacom_data->irq);
137
138 return 0;
139 }
140
wacom_w9000_power_off(struct wacom_w9000_data * wacom_data)141 static int wacom_w9000_power_off(struct wacom_w9000_data *wacom_data)
142 {
143 lockdep_assert_held(&wacom_data->input_dev->mutex);
144
145 disable_irq(wacom_data->irq);
146 gpiod_set_value_cansleep(wacom_data->reset_gpio, 1);
147 regulator_disable(wacom_data->regulator);
148
149 return 0;
150 }
151
wacom_w9000_coord(struct wacom_w9000_data * wacom_data)152 static void wacom_w9000_coord(struct wacom_w9000_data *wacom_data)
153 {
154 struct i2c_client *client = wacom_data->client;
155 struct device *dev = &wacom_data->client->dev;
156 u8 data[MSG_COORD_NUM_MAX];
157 bool touch, rubber, side_button;
158 u16 x, y, pressure;
159 u8 distance = 0;
160 int error;
161
162 error = i2c_master_recv(client, data, wacom_data->variant->msg_coord_num);
163 if (error != wacom_data->variant->msg_coord_num) {
164 if (error >= 0)
165 error = -EIO;
166 dev_err_ratelimited(dev, "%s: i2c receive failed (%d)\n", __func__, error);
167 return;
168 }
169
170 dev_dbg(dev, "data: %*ph\n", wacom_data->variant->msg_coord_num, data);
171
172 if (data[0] & BIT(7)) {
173 wacom_data->pen_proximity = true;
174
175 touch = !!(data[0] & BIT(4));
176 side_button = !!(data[0] & BIT(5));
177 rubber = !!(data[0] & BIT(6));
178
179 x = get_unaligned_be16(&data[1]);
180 y = get_unaligned_be16(&data[3]);
181 pressure = get_unaligned_be16(&data[5]);
182
183 if (wacom_data->variant->msg_coord_num > 7)
184 distance = data[7];
185
186 if (x > wacom_data->prop.max_x || y > wacom_data->prop.max_y) {
187 dev_warn_ratelimited(dev, "Coordinates out of range x=%d, y=%d\n", x, y);
188 return;
189 }
190
191 if (pressure > wacom_data->max_pressure) {
192 dev_warn_ratelimited(dev, "Pressure out of range %d\n", pressure);
193 return;
194 }
195
196 touchscreen_report_pos(wacom_data->input_dev, &wacom_data->prop, x, y, false);
197 input_report_abs(wacom_data->input_dev, ABS_PRESSURE, pressure);
198
199 if (wacom_data->variant->msg_coord_num > 7)
200 input_report_abs(wacom_data->input_dev, ABS_DISTANCE, distance);
201
202 input_report_key(wacom_data->input_dev, BTN_STYLUS, side_button);
203 input_report_key(wacom_data->input_dev, BTN_TOUCH, touch);
204 input_report_key(wacom_data->input_dev, BTN_TOOL_PEN, !rubber);
205 input_report_key(wacom_data->input_dev, BTN_TOOL_RUBBER, rubber);
206 input_sync(wacom_data->input_dev);
207 } else if (wacom_data->pen_proximity) {
208 input_report_abs(wacom_data->input_dev, ABS_PRESSURE, 0);
209
210 if (wacom_data->variant->msg_coord_num > 7)
211 input_report_abs(wacom_data->input_dev, ABS_DISTANCE, 255);
212
213 input_report_key(wacom_data->input_dev, BTN_STYLUS, 0);
214 input_report_key(wacom_data->input_dev, BTN_TOUCH, 0);
215 input_report_key(wacom_data->input_dev, BTN_TOOL_PEN, 0);
216 input_report_key(wacom_data->input_dev, BTN_TOOL_RUBBER, 0);
217 input_sync(wacom_data->input_dev);
218
219 wacom_data->pen_proximity = false;
220 }
221 }
222
wacom_w9000_interrupt(int irq,void * dev_id)223 static irqreturn_t wacom_w9000_interrupt(int irq, void *dev_id)
224 {
225 struct wacom_w9000_data *wacom_data = dev_id;
226
227 wacom_w9000_coord(wacom_data);
228
229 return IRQ_HANDLED;
230 }
231
wacom_w9000_open(struct input_dev * dev)232 static int wacom_w9000_open(struct input_dev *dev)
233 {
234 struct wacom_w9000_data *wacom_data = input_get_drvdata(dev);
235
236 return wacom_w9000_power_on(wacom_data);
237 }
238
wacom_w9000_close(struct input_dev * dev)239 static void wacom_w9000_close(struct input_dev *dev)
240 {
241 struct wacom_w9000_data *wacom_data = input_get_drvdata(dev);
242
243 wacom_w9000_power_off(wacom_data);
244 }
245
wacom_w9000_probe(struct i2c_client * client)246 static int wacom_w9000_probe(struct i2c_client *client)
247 {
248 struct device *dev = &client->dev;
249 struct wacom_w9000_data *wacom_data;
250 struct input_dev *input_dev;
251 int error;
252 u32 val;
253
254 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
255 dev_err(dev, "i2c_check_functionality error\n");
256 return -EIO;
257 }
258
259 wacom_data = devm_kzalloc(dev, sizeof(*wacom_data), GFP_KERNEL);
260 if (!wacom_data)
261 return -ENOMEM;
262
263 wacom_data->variant = i2c_get_match_data(client);
264 if (!wacom_data->variant) {
265 dev_err(dev, "No i2c match_data available\n");
266 return -EINVAL;
267 }
268
269 if (wacom_data->variant->cmd_query_num > CMD_QUERY_NUM_MAX ||
270 wacom_data->variant->msg_coord_num > MSG_COORD_NUM_MAX) {
271 dev_err(dev, "Length of message for %s exceeds the maximum\n",
272 wacom_data->variant->name);
273 return -EINVAL;
274 }
275
276 if (wacom_data->variant->msg_coord_num < 7) {
277 dev_err(dev, "Length of coordinates message for %s too short\n",
278 wacom_data->variant->name);
279 return -EINVAL;
280 }
281
282 wacom_data->client = client;
283 wacom_data->irq = client->irq;
284 i2c_set_clientdata(client, wacom_data);
285
286 wacom_data->regulator = devm_regulator_get(dev, "vdd");
287 if (IS_ERR(wacom_data->regulator))
288 return dev_err_probe(dev, PTR_ERR(wacom_data->regulator),
289 "Failed to get regulators\n");
290
291 wacom_data->flash_mode_gpio = devm_gpiod_get_optional(dev, "flash-mode", GPIOD_OUT_LOW);
292 if (IS_ERR(wacom_data->flash_mode_gpio))
293 return dev_err_probe(dev, PTR_ERR(wacom_data->flash_mode_gpio),
294 "Failed to get flash-mode gpio\n");
295
296 wacom_data->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
297 if (IS_ERR(wacom_data->reset_gpio))
298 return dev_err_probe(dev, PTR_ERR(wacom_data->reset_gpio),
299 "Failed to get reset gpio\n");
300
301 error = regulator_enable(wacom_data->regulator);
302 if (error)
303 return dev_err_probe(dev, error, "Failed to enable regulators\n");
304
305 msleep(200);
306
307 gpiod_set_value_cansleep(wacom_data->reset_gpio, 0);
308
309 error = wacom_w9000_query(wacom_data);
310
311 gpiod_set_value_cansleep(wacom_data->reset_gpio, 1);
312 regulator_disable(wacom_data->regulator);
313
314 if (error)
315 return dev_err_probe(dev, error, "Failed to query\n");
316
317 error = devm_request_threaded_irq(dev, wacom_data->irq, NULL, wacom_w9000_interrupt,
318 IRQF_ONESHOT | IRQF_NO_AUTOEN, client->name, wacom_data);
319 if (error)
320 return dev_err_probe(dev, error, "Failed to register interrupt\n");
321
322 input_dev = devm_input_allocate_device(dev);
323 if (!input_dev)
324 return -ENOMEM;
325
326 wacom_data->input_dev = input_dev;
327 input_set_drvdata(input_dev, wacom_data);
328
329 input_dev->name = wacom_data->variant->name;
330 input_dev->id.bustype = BUS_I2C;
331 input_dev->id.vendor = 0x56a;
332 input_dev->id.version = wacom_data->fw_version;
333 input_dev->open = wacom_w9000_open;
334 input_dev->close = wacom_w9000_close;
335
336 input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
337 input_set_capability(input_dev, EV_KEY, BTN_TOOL_PEN);
338 input_set_capability(input_dev, EV_KEY, BTN_TOOL_RUBBER);
339 input_set_capability(input_dev, EV_KEY, BTN_STYLUS);
340
341 input_set_abs_params(input_dev, ABS_X, 0, wacom_data->prop.max_x, 4, 0);
342 input_set_abs_params(input_dev, ABS_Y, 0, wacom_data->prop.max_y, 4, 0);
343 input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_data->max_pressure, 0, 0);
344
345 if (wacom_data->variant->msg_coord_num > 7)
346 input_set_abs_params(input_dev, ABS_DISTANCE, 0, 255, 0, 0);
347
348 touchscreen_parse_properties(input_dev, false, &wacom_data->prop);
349
350 dev_info(dev, "%s size X%uY%u\n", wacom_data->variant->name,
351 wacom_data->prop.max_x, wacom_data->prop.max_y);
352
353 error = device_property_read_u32(dev, "touchscreen-x-mm", &val);
354 if (!error && val)
355 input_abs_set_res(input_dev, wacom_data->prop.swap_x_y ? ABS_Y : ABS_X,
356 wacom_data->prop.max_x / val);
357 error = device_property_read_u32(dev, "touchscreen-y-mm", &val);
358 if (!error && val)
359 input_abs_set_res(input_dev, wacom_data->prop.swap_x_y ? ABS_X : ABS_Y,
360 wacom_data->prop.max_y / val);
361
362 error = input_register_device(wacom_data->input_dev);
363 if (error)
364 return dev_err_probe(dev, error, "Failed to register input device\n");
365
366 return 0;
367 }
368
wacom_w9000_suspend(struct device * dev)369 static int wacom_w9000_suspend(struct device *dev)
370 {
371 struct i2c_client *client = to_i2c_client(dev);
372 struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
373
374 guard(mutex)(&wacom_data->input_dev->mutex);
375
376 if (input_device_enabled(wacom_data->input_dev))
377 return wacom_w9000_power_off(wacom_data);
378
379 return 0;
380 }
381
wacom_w9000_resume(struct device * dev)382 static int wacom_w9000_resume(struct device *dev)
383 {
384 struct i2c_client *client = to_i2c_client(dev);
385 struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
386
387 guard(mutex)(&wacom_data->input_dev->mutex);
388
389 if (input_device_enabled(wacom_data->input_dev))
390 return wacom_w9000_power_on(wacom_data);
391
392 return 0;
393 }
394
395 static DEFINE_SIMPLE_DEV_PM_OPS(wacom_w9000_pm, wacom_w9000_suspend, wacom_w9000_resume);
396
397 static const struct wacom_w9000_variant w9002 = {
398 .cmd_query_num = 9,
399 .msg_coord_num = 7,
400 .name = "Wacom W9002 Digitizer",
401 };
402
403 static const struct wacom_w9000_variant w9007a_lt03 = {
404 .cmd_query_num = 9,
405 .msg_coord_num = 8,
406 .name = "Wacom W9007A LT03 Digitizer",
407 };
408
409 static const struct wacom_w9000_variant w9007a_v1 = {
410 .cmd_query_num = 9,
411 .msg_coord_num = 12,
412 .name = "Wacom W9007A V1 Digitizer",
413 };
414
415 static const struct of_device_id wacom_w9000_of_match[] = {
416 { .compatible = "wacom,w9002", .data = &w9002 },
417 { .compatible = "wacom,w9007a-lt03", .data = &w9007a_lt03, },
418 { .compatible = "wacom,w9007a-v1", .data = &w9007a_v1, },
419 { }
420 };
421 MODULE_DEVICE_TABLE(of, wacom_w9000_of_match);
422
423 static const struct i2c_device_id wacom_w9000_id[] = {
424 { .name = "w9002", .driver_data = (kernel_ulong_t)&w9002 },
425 { .name = "w9007a-lt03", .driver_data = (kernel_ulong_t)&w9007a_lt03 },
426 { .name = "w9007a-v1", .driver_data = (kernel_ulong_t)&w9007a_v1 },
427 { }
428 };
429 MODULE_DEVICE_TABLE(i2c, wacom_w9000_id);
430
431 static struct i2c_driver wacom_w9000_driver = {
432 .driver = {
433 .name = "wacom_w9000",
434 .of_match_table = wacom_w9000_of_match,
435 .pm = pm_sleep_ptr(&wacom_w9000_pm),
436 },
437 .probe = wacom_w9000_probe,
438 .id_table = wacom_w9000_id,
439 };
440 module_i2c_driver(wacom_w9000_driver);
441
442 MODULE_AUTHOR("Hendrik Noack <hendrik-noack@gmx.de>");
443 MODULE_DESCRIPTION("Wacom W9000-series penabled touchscreen driver");
444 MODULE_LICENSE("GPL");
445