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