xref: /linux/drivers/input/touchscreen/wacom_w9000.c (revision 3d5e48944e824bddc20d7b874e784f7b279636fe)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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